请解释 Java 中 synchronized 关键字的底层实现原理,并说明锁的升级与降级机制的具体过程。
考察说明
考查 synchronized 底层实现和锁升级降级机制,关注对 JVM 对象头与监控器的理解。
回答思路
- 【回答框架 1】synchronized 在 JVM 中通过 Monitor(监视器锁)实现,每个对象关联一个 monitor,monitor 由 ObjectMonitor 结构管理,包含 owner、entry list、wait set 等字段。字节码层面使用 monitorenter 和 monitorexit 指令,同步方法则通过方法的 ACC_SYNCHRONIZED 标志隐式使用。
- 【回答框架 2】锁升级通常指从偏向锁到轻量级锁再到重量级锁的升级过程。偏向锁通过 CAS 将对象头 Mark Word 中的线程 ID 指向当前线程,避免每次加锁都有 CAS 竞争;当有其他线程竞争时,升级为轻量级锁,线程在栈帧中创建锁记录(Lock Record),使用 CAS 将对象头替换为指向锁记录的指针,失败则自旋获取;自旋超限或竞争加剧则升级为重量级锁,线程被阻塞并进入操作系统的互斥量。
- 【回答框架 3】锁降级在 HotSpot JVM 中是指当 JVM 进入 SafePoint 时,对不再有竞争的重偏向锁或轻量级锁进行状态重置,例如清空偏向锁的线程 ID,使其恢复到无锁或可重偏向状态。锁降级通常发生在偏向锁被撤销或轻量级锁释放时,但重量级锁一般不会直接降级为轻量级锁。
- 【回答框架 4】锁升级不可逆,但偏向锁可被撤销并重置;轻量级锁在竞争不激烈时可通过自旋和 CAS 保持性能,但升级到重量级锁后性能下降。JDK 15 默认偏向锁已废弃,但底层锁机制仍依赖 Mark Word 和对象监控器,具体行为与 JVM 版本相关。
- 【关键点 1】synchronized 基于对象头的 Mark Word 和 Monitor 实现,monitorenter/monitorexit 控制进入与退出。
- 【关键点 2】锁升级路径为偏向锁、轻量级锁、重量级锁,升级不可逆,偏向锁可撤销重置。
- 【关键点 3】轻量级锁使用 CAS 与自旋,重量级锁依赖 OS 互斥量,会导致线程阻塞和上下文切换。
- 【关键点 4】锁降级发生在 SafePoint 时,主要用于清理偏向锁,重量级锁不降级。
- 【易错点 1】不能将偏向锁与轻量级锁的 CAS 过程混淆,偏向锁只在初始无竞争时使用,轻量级锁引入竞争后使用 CAS。
- 【易错点 2】锁降级并非常规优化,而是 JVM 在安全点时的清理机制,不承诺重量级锁可降级。
- 【易错点 3】忽视锁升级对性能的影响,重量级锁竞争会导致高昂的阻塞开销,需通过减少竞争或使用无锁结构改善。