Synchronized-轻量级锁

1,260 阅读2分钟

纸上得来终觉浅,绝知此事要躬行。

轻量级锁是什么?

是jdk1.6引入的一种锁优化方式。传统的重量级锁加锁需要使用操作系统的互斥量实现。消耗较大。引入轻量级锁在没有多线程竞争的前提下,通过jvm来实现加锁,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。

轻量级锁提升性能的依据

对绝大部分的锁,在整个同步周期内都不存在竞争。即线程交替执行同步代码块(一个线程执行完,第二个线程才来访问执行)。 当存在两个线程同时访问一个同步代码块时,会从轻量级锁升级为重量级锁。

什么情况会升级为轻量级锁

1. 无锁

偏向标识0为不可偏向。

2. 已偏向

偏向标识为1,但已偏向为某个线程(非当前线程),且无法进行重偏向。会进行锁升级,升级为轻量级锁。

轻量级锁加锁过程

  1. 判断锁标识,是否满足升级为轻量级锁条件。

    1. 锁标识为001,表示无锁,并且不可偏向。
    2. 锁标识为000时,为轻量级锁,走轻量级锁重入逻辑
  2. 在栈中记录一条Lock Reocrd,并将对象的Mark Word备份到Lock Record.Displaced Mark Word中(用于后续还原),将owner指向当前对象。

    1. image.png
  3. 尝试通过CAS将锁对象的Mark Word更新为指向Lock Record的指针,并更新锁状态为00

image.png

  1. 如果对象是轻量级锁标识,判断Mark Word是否指向当前线程的栈帧。如果是则为锁重入。将Lock Record.Displaced Mark Word设置为null,如果不是,执行5
  2. 线程获取轻量级锁失败,锁膨胀为重量级锁,对象头Mark Word改为指向重量级锁monitor的指针。获取锁失败的线程不会立即阻塞,先适应性自旋,尝试获取锁。到达临界值后,阻塞该线程,直到唤醒。

轻量级锁解锁过程

  1. 获取最新的一条Lock Record,如果Displaced Mark Wordnull,如果是,则将owner设置为null,如果不是执行2
  2. 通过CAS把当前线程栈帧的Lock Record中的Displaced Mark Word替换到对象头的Mark Word,如果替换成功,则轻量级锁解锁成功。如果替换失败,则说明Mark Word已经被替换为指向Monitor,对象现在是重量级锁定状态,执行重量级锁释放。

参考文献

CSDN Synchronized原理(轻量级锁)