当前位置: 首页 > 面试题库 >

Java:什么是锁消除和锁粗化?

汪才
2023-04-24

(1)锁消除

所消除就是虚拟机根据一个对象是否真正存在同步情况,若不存在同步情况,则对该对象的访问无需经过加锁解锁的操作。

比如StringBuffer的append方法,因为append方法需要判断对象是否被占用,而如果代码不存在锁竞争,那么这部分的性能消耗是无意义的。于是虚拟机在即时编译的时候就会将上面的代码进行优化,也就是锁消除。

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

从源码可以看出,append方法用了 synchronized关键字,它是线程安全的。但我们可能仅在线程内部把StringBuffer当做局部变量使用;StringBuffer仅在方法内作用域有效,不存在线程安全的问题,这时我们可以通过编译器将其优化,将锁消除,前提是Java必须运行在server模式,同时必须开启逃逸分析;

-server -XX:+DoEscapeAnalysis -XX:+EliminateLocks
 
其中+DoEscapeAnalysis表示开启逃逸分析,+EliminateLocks表示锁消除。
public static String createStringBuffer(String str1, String str2) {
    StringBuffer sBuf = new StringBuffer();
    sBuf.append(str1);// append方法是同步操作
    sBuf.append(str2);
    return sBuf.toString();
}

逃逸分析:比如上面的代码,它要看sBuf是否可能逃出它的作用域?如果将sBuf作为方法的返回值进行返回,那么它在方法外部可能被当作一个全局对象使用,就有可能发生线程安全问题,这时就可以说sBuf这个对象发生逃逸了,因而不应将append操作的锁消除,但我们上面的代码没有发生锁逃逸,锁消除就可以带来一定的性能提升。 

(2)锁粗化

锁的请求、同步、释放都会消耗一定的系统资源,如果高频的锁请求反而不利于系统性能的优化,锁粗化就是把多次的锁请求合并成一个请求,扩大锁的范围,降低锁请求、同步、释放带来的性能损耗。

 类似资料:
  • 锁粗化 通常情况下,为了保证多线程间的有效并发,会要求每个线程持有锁的时间尽可能短,但是大某些情况下,一个程序对同一个锁不间断、高频地请求、同步与释放,会消耗掉一定的系统资源,因为锁的讲求、同步与释放本身会带来性能损耗,这样高频的锁请求就反而不利于系统性能的优化了,虽然单次同步操作的时间可能很短。锁粗化就是告诉我们任何事情都有个度,有些情况下我们反而希望把很多次锁的请求合并成一个请求,以降低短时间

  • 锁粗化 通常情况下,为了保证多线程间的有效并发,会要求每个线程持有锁的时间尽可能短,但是大某些情况下,一个程序对同一个锁不间断、高频地请求、同步与释放,会消耗掉一定的系统资源,因为锁的讲求、同步与释放本身会带来性能损耗,这样高频的锁请求就反而不利于系统性能的优化了,虽然单次同步操作的时间可能很短。锁粗化就是告诉我们任何事情都有个度,有些情况下我们反而希望把很多次锁的请求合并成一个请求,以降低短时间

  • 本文向大家介绍什么是锁?相关面试题,主要包含被问及什么是锁?时的应答技巧和注意事项,需要的朋友参考一下 数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。 加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加

  • 本文向大家介绍什么是事务?什么是锁?相关面试题,主要包含被问及什么是事务?什么是锁?时的应答技巧和注意事项,需要的朋友参考一下 答:事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔

  • 本文向大家介绍什么是线程死锁?如何避免死锁?相关面试题,主要包含被问及什么是线程死锁?如何避免死锁?时的应答技巧和注意事项,需要的朋友参考一下 认识线程死锁 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态

  • 问题内容: 我有一个客户端服务器程序在服务器端使用套接字,并且读写发生在这种方式 同样在cilent(android)方面… 问题是,建立连接后,程序会卡住它们,没有错误,也没有异常。停下来 问题答案: 这是一个死锁,您必须首先创建并刷新ObjectOutputStream。这是因为ObjectInputStream在继续操作之前先读取OOS发送的标头。