线程安全与锁优化

2018-10-31  本文已影响0人  tangyu_tyty

一、线程安全的实现方法

(一)互斥同步

(二)非阻塞同步

二、锁优化

(一)自旋锁与自适应自旋

(二)锁消除

(三)锁粗化

(四)轻量级锁

1、轻量级锁的加锁过程:

在代码进入同步块的时候,如果此同步对象没有被锁定(锁标识为01状态),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝(官方把这个拷贝叫Displaced Mark Word)。然后虚拟机将使用cas操作尝试将对象的mark word更新为指向Lock Record的指针。

如果这个更新动作成功了,那么这个线程就拥有了该对象的锁,并且对象Mark Word的锁标志位将转变为00,即表示此对象处于轻量级锁定状态。

如果这个更新动作失败了,虚拟机首先会检查对象Mark Word是否指向当前线程的栈帧,如果只说明当前线程已经拥有了这个对象的锁,那就可以直接进入同步块继续执行,否则说明这个锁对象已经被其他线程抢占了。

如果有两条以上的线程争用同一个锁,那轻量级锁就不再有效,要膨胀为重量级锁,锁标志位的状态变为10Mark Word中存储的就是指向重量级锁(互斥量)的指针,后面等待锁的线程也要进入阻塞状态。

2、轻量级锁的解锁过程

解锁过程也是通过cas操作来进行的,如果对象的Mark Word仍然指向线程的锁记录,那就用cas操作把对象当前的Mark Word和线程中复制的Displaced Mark Word替换回来,如果替换成功了,整个同步过程就完成了。如果替换失败,说明有其他线程尝试过获取该锁,那就要在释放锁的同时,唤醒被挂起的线程。

(五)偏向锁

1、偏向锁原理

假设当前虚拟机启用了偏向锁(==-XX:+UseBiasedLocking,这是jdk1.6的默认值==),那么当锁对象第一次被线程获取的时候,虚拟机将会把对象头中的标志位设为01,即偏向模式。同时使用cas操作把获取到这个锁的线程的id记录在对象Mark Word之中,如果cas操作成功,持有偏向锁的线程以后每次进入这个锁相关的同步块时,虚拟机都可以不再进行任何同步操作(例如LockingUnlocking及对Mark WordUpdate等)。

当有另外一个线程去尝试获取这个锁时,偏向模式就宣告结束。根据锁对象目前是否处于被锁定的状态,撤销偏向后恢复到未锁定(标志位为01)或轻量级锁(标志位为00)的状态。后续的同步操作就如上面介绍的轻量级锁那样执行。
如果程序中大多数的锁总是被多个不同的线程访问,那偏向模式就是多余的,使用-XX:-UseBiasedLocking来禁止偏向锁优化反而可以提升性能。

上一篇下一篇

猜你喜欢

热点阅读