JVM锁优化

自旋锁和自适应自旋

自旋锁是当多个线程并行访问共享数据时,用忙循环让后面请求锁的线程处于等待状态,当自旋多次后仍然获取不到锁,再用传统的方式将线程挂起。
忙循环就是用循环让线程等待,忙循环也叫自旋。
在Java6之后,如果有线程刚通过自旋获得了锁,并且线程正在运行,那么JVM会认为自旋获取锁的命中率高,其他线程的自旋次数可能会增多。如果某个锁通过自旋获得的次数少,JVM可能会省略掉自旋获取锁,直接挂起线程去等待锁。

锁消除

锁消除是指JVM即时编译器运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据的竞争,那么锁会进行消除。
它判断的依据是通过判断一段代码在堆上的所有数据不会逃逸,被其他线程访问到,那么认为它是线程私有的,进行锁消除。

锁粗化

编写代码时,要求同步代码块的范围越小越好。但是在某些情况下,例如在循环中调用StringBuffer#append方法,这会对一个对象反复加锁,如果出现这类情况,JVM会将锁同步的范围优化到整个操作的外面,让程序加一次锁就行了。

轻量级锁和偏向锁

轻量级锁和偏向锁都是通过对象头信息中的锁标志位进行锁优化。
在对象头的Mark Word中,有两个位是锁标志位。00表示未锁定、01表示轻量级锁定、10表示重量级锁。

  • 轻量级锁

    轻量级锁是指在代码执行到同步块时,如果同步对象未锁定,JVM会在当前线程的栈帧中创建一个锁记录,然后使用CAS将对象的Mark Word更新为执行锁记录的指针,如果操作成功,表示线程获得锁,将锁标志位变为00。如果失败,首先判断对象的Mark Word是否指向当前线程的栈帧,如果是,可以直接进入同步块执行,否则说明锁被其他线程占有了。如果有两条以上的线程争用同一个锁,那么轻量级锁就失效了,变为重量级锁10。

  • 偏向锁

    偏向锁是指锁对象会偏向于第一个获得它的线程,如果之后锁对象不再被其他线程获取,那么持有偏向锁的线程永远不用再进行同步。当锁对象第一次被线程获取时,JVM将锁标志改为01,并用CAS把获取到锁的线程ID记录到对象的Mark Word中。如果CAS成功,持有偏向锁的线程以后每次执行同步块时,JVM都不会有任何同步操作。但是当有另外的线程尝试获取这个锁时,偏向模式就结束了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章