(JUC)Java中的锁升级机制 AI整理
一、前言
在 Java 并发编程中,synchronized 是最常用的关键字。
JDK1.6 之前,synchronized 被认为是重量级锁,性能开销较大;而在 JDK1.6 之后,HotSpot 虚拟机引入了 锁优化机制,包括 锁升级(Lock Escalation/Lock Inflation) 和 锁消除、锁粗化 等,从而大幅度提升了 synchronized 的性能。
其中,锁升级机制 是理解 JVM 同步优化的核心。
二、锁的几种状态
在 HotSpot JVM 中,锁一共有四种状态,它们会随着竞争情况逐步升级:
-
无锁(No Lock)
-
对象没有被任何线程加锁,正常访问。
-
-
偏向锁(Biased Lock)
-
线程第一次获得锁时,会在对象头记录当前线程的 ID。
-
后续该线程再进入同步块时,不需要进行 CAS 操作,直接判断对象头是否偏向自己,从而几乎零成本加锁。
-
-
轻量级锁(Lightweight Lock)
-
当另外一个线程尝试获取锁时,会通过 CAS 自旋 竞争。
-
如果自旋成功,则升级为轻量级锁。
-
适用于 线程交替执行 的情况。
-
-
重量级锁(Heavyweight Lock)
-
当竞争激烈时,轻量级锁会膨胀为重量级锁。
-
线程会被阻塞,进入等待队列,由操作系统调度。
-
性能较差,但保证了线程安全。
-
三、锁升级的过程
锁升级是 不可逆的,即:
-
偏向锁 → 轻量级锁 → 重量级锁
-
一旦升级,不会再降级。
1. 偏向锁 → 轻量级锁
-
当一个对象已经被线程 A 持有(偏向 A),线程 B 也来尝试获取锁时,会触发升级。
-
偏向锁会撤销,进入轻量级锁竞争。
2. 轻量级锁 → 重量级锁
-
如果轻量级锁的 CAS 自旋失败(比如同时多个线程激烈竞争),JVM 会将锁膨胀为重量级锁。
-
此时,未抢到锁的线程会被阻塞,等待唤醒。
四、对象头与 Mark Word
Java 对象头里存储了锁的状态,主要依赖于 Mark Word(标记字段)。
-
无锁:Mark Word 里存放对象的哈希值、GC 分代年龄等信息。
-
偏向锁:Mark Word 里存放线程 ID、偏向时间戳。
-
轻量级锁:Mark Word 存放指向线程栈中 Lock Record 的指针。
-
重量级锁:Mark Word 指向 Monitor 对象(OS 级别的互斥量)。
五、直观比喻
-
偏向锁:宿舍门只贴了一张“专属你”的便利贴,你回来不用再刷卡。
-
轻量级锁:如果室友也想进,就大家在门口“试试钥匙”,谁先插进去谁进。
-
重量级锁:如果人太多,大家只能排队,宿管阿姨(OS)来统一调度。
六、为什么要锁升级?
-
性能优化
-
偏向锁:单线程反复进入同步块时最快。
-
轻量级锁:短时间的少量竞争,可以避免操作系统调度开销。
-
重量级锁:多线程激烈竞争时保证安全。
-
-
适配不同场景
-
单线程:偏向锁最佳。
-
多线程但冲突少:轻量级锁更高效。
-
高并发竞争:重量级锁稳定安全。
-
七、总结
-
锁的状态:无锁 → 偏向锁 → 轻量级锁 → 重量级锁。
-
升级是 单向的,不可逆。
-
synchronized在 JDK1.6 之后性能大幅提升,已经可以在很多场景媲美ReentrantLock。 -
了解锁升级,有助于理解 Java 并发优化原理,避免误以为
synchronized总是低效。
更多推荐

所有评论(0)