请说明Java中synchronized关键字的底层实现机制,包括其在不同情况下的加锁对象、相关的锁状态与升级过程,以及涉及的底层指令或数据结构。
考察说明
考察对Java同步机制底层实现的理解,特别是锁升级和底层原理。
回答思路
- 【回答框架 1】synchronized在Java中用于实现方法或代码块的同步,其基于监视器锁(Monitor)实现,每个对象关联一个监视器,通过底层指令(如monitorenter和monitorexit)或对象头中的锁状态控制访问。
- 【回答框架 2】对于不同同步场景,锁对象不同:同步实例方法锁当前对象实例;同步静态方法锁该类的Class对象;同步代码块锁指定对象。锁信息存储在对象头中,包含Mark Word,记录锁状态和持有线程等信息。
- 【回答框架 3】锁具有升级过程:无锁、偏向锁、轻量级锁、重量级锁。偏向锁减少无竞争时的开销,轻量级锁适用于少量竞争,重量级锁由操作系统互斥量实现,涉及线程阻塞和唤醒。升级基于竞争程度,从偏向锁到重量级锁,不能降级。
- 【回答框架 4】偏向锁在无竞争时直接CAS设置线程ID;若产生竞争则撤销偏向并升级为轻量级锁,轻量级锁通过自旋尝试获取;自旋超过阈值或竞争加剧则膨胀为重量级锁,使用操作系统的mutex进行阻塞。JVM通过自适应自旋和锁消除等优化提升性能。
- 【关键点 1】synchronized基于对象监视器实现,通过字节码指令和对象头中的锁状态控制同步。
- 【关键点 2】锁状态包括无锁、偏向锁、轻量级锁、重量级锁,按竞争程度升级。
- 【关键点 3】对象头中的Mark Word存储锁状态、持有线程ID或指向锁记录的指针。
- 【关键点 4】偏向锁适用于单线程访问场景,轻量级锁适用于轻度竞争,重量级锁涉及操作系统级阻塞。
- 【易错点 1】将锁升级理解为可逆过程,实际偏向锁撤销后无法重新偏向,只能升级。
- 【易错点 2】误认为轻量级锁总是比重量级锁快,高竞争下自旋浪费CPU,重量级锁通过阻塞避免忙等。
- 【易错点 3】忽略synchronized在实例方法和静态方法上的锁对象差异,导致同步失效或过度同步。