纸上得来终觉浅,绝知此事要躬行。
轻量级锁是什么?
是jdk1.6引入的一种锁优化方式。传统的重量级锁加锁需要使用操作系统的互斥量实现。消耗较大。引入轻量级锁在没有多线程竞争的前提下,通过jvm来实现加锁,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。
轻量级锁提升性能的依据
对绝大部分的锁,在整个同步周期内都不存在竞争。即线程交替执行同步代码块(一个线程执行完,第二个线程才来访问执行)。 当存在两个线程同时访问一个同步代码块时,会从轻量级锁升级为重量级锁。
什么情况会升级为轻量级锁
1. 无锁
偏向标识0为不可偏向。
2. 已偏向
偏向标识为1,但已偏向为某个线程(非当前线程),且无法进行重偏向。会进行锁升级,升级为轻量级锁。
轻量级锁加锁过程
-
判断锁标识,是否满足升级为轻量级锁条件。
- 锁标识为
001,表示无锁,并且不可偏向。 - 锁标识为
000时,为轻量级锁,走轻量级锁重入逻辑
- 锁标识为
-
在栈中记录一条
Lock Reocrd,并将对象的Mark Word备份到Lock Record.Displaced Mark Word中(用于后续还原),将owner指向当前对象。 -
尝试通过CAS将锁对象的
Mark Word更新为指向Lock Record的指针,并更新锁状态为00
- 如果对象是轻量级锁标识,判断
Mark Word是否指向当前线程的栈帧。如果是则为锁重入。将Lock Record.Displaced Mark Word设置为null,如果不是,执行5 - 线程获取轻量级锁失败,锁膨胀为重量级锁,对象头
Mark Word改为指向重量级锁monitor的指针。获取锁失败的线程不会立即阻塞,先适应性自旋,尝试获取锁。到达临界值后,阻塞该线程,直到唤醒。
轻量级锁解锁过程
- 获取最新的一条
Lock Record,如果Displaced Mark Word为null,如果是,则将owner设置为null,如果不是执行2 - 通过CAS把当前线程栈帧的
Lock Record中的Displaced Mark Word替换到对象头的Mark Word,如果替换成功,则轻量级锁解锁成功。如果替换失败,则说明Mark Word已经被替换为指向Monitor,对象现在是重量级锁定状态,执行重量级锁释放。