文章目录
1. 轻量级锁分析
回顾重量级锁
在上文 Java并发 | 17.[锁机制] 重量级锁(Monitor+自旋锁)中对重量级锁进行过解析,需要实现重量级锁,就要向操作系统申请一个 Monitor 对象。
轻量级锁的优势
轻量级锁使用CAS和自旋锁来获取锁,避免了向操作系统申请 Monitor 对象,从而减少性能消耗。
2. CAS(Compare And Swap)
顾名思义,在进行比较后如果满足条件,就会交换内容。
在轻量级锁机制中,则是判断 obj 中 Mark Word 是否为 "指向LockRecord"的指针,若不是,则将当前线程中 “LockRecord 里指向自己的指针” 与 MarkWord 交换。
3. 轻量级锁(CAS+自旋锁)
3.1. 整体流程图
3.2. 加锁、锁重入、锁释放(CAS)
- [加锁] 线程t1发现 obj 的 MarkWord 不是「指向LockRecord的指针」,于是 将指向LockRecord的指针与MarkWord 进行交换(CAS);
- [锁重入] 当一段 synchronized( obj1 ) 代码块中递归地执行了 synchronized( obj1 ) 代码块,就会出现「锁重入」,此时虽然CAS失败,但线程t1发现指针指向的 LockRecord 是属于自己的,于是创建一个新的 LockRecord 用于计数;
- [锁释放] 当 synchronized( obj ) 代码块执行完毕,则 将MarkWord与指向LockRecord的指针 换回原来的位置(再次CAS)。
3.3. 锁膨胀(CAS+自旋)
若发生了锁竞争(线程t2尝试CAS失败,并发现对象头中指针指向的LockRecord并不属于自己),那线程t2就会循环 争抢锁,直到超出次数上限(默认10次,JVM底层会自适应调整),就会将锁升级为「重量级锁」。
- [申请Monitor] 向操作系统申请一个 Monitor 对象;
- [重置指针、进入EntryList] obj 中的指针被替换成「指向Monitor的指针」,Monitor 中的 Owner 指向 t1,t2 进入 EntryList 并进入 BLOCKED 状态;
- [唤醒t2] t1 执行完毕后,尝试 CAS 失败,说明锁已进行过升级,于是根据JVM底层算法,唤醒 EntryList 中的某个线程,并使之成为「重量级锁」的新 Owner。