在 Java 中,synchronized 轻量级锁的实现是否会涉及自旋操作?请说明其原理。
考察说明
考查对 synchronized 锁升级机制中轻量级锁实现细节的理解,尤其是自旋在锁竞争处理中的作用。
回答思路
- 【回答框架 1】轻量级锁是 Java 偏向锁之后、重量级锁之前的一种锁状态,基于 CAS 和对象头 Mark Word 实现,用于减少重量级锁带来的线程阻塞和唤醒开销。
- 【回答框架 2】当线程尝试获取轻量级锁时,会通过 CAS 将对象头中的 Mark Word 替换为指向当前线程栈帧中锁记录的指针。若 CAS 成功则持有锁;若失败,说明存在竞争,此时会进行自旋。
- 【回答框架 3】自旋是轻量级锁竞争失败后的一种优化策略:线程不立即阻塞,而是短暂循环重试 CAS,以避免线程切换的开销。JDK 1.6 之后引入自适应自旋,自旋次数由前一次在同一个锁上的自旋时间和锁拥有者状态决定。
- 【回答框架 4】自旋并非轻量级锁独有的机制,重量级锁竞争时也可能通过自旋避免直接进入阻塞队列。但需注意,长时间自旋会浪费 CPU 资源,因此自旋失败达到阈值后会锁膨胀为重量级锁,线程进入阻塞队列。
- 【关键点 1】轻量级锁获取失败后会进行自旋,自旋是获取锁的优化机制。
- 【关键点 2】自旋通过 CAS 循环尝试获取锁,避免线程阻塞和唤醒的代价。
- 【关键点 3】JDK 1.6 后自旋为自适应,次数动态调整。
- 【关键点 4】自旋失败会触发锁膨胀,升级为重量级锁。
- 【关键点 5】自旋不等于自旋锁,自旋锁是独立的锁类型,此处是轻量级锁内的竞争处理。
- 【易错点 1】误认为轻量级锁一定不会自旋,实际上竞争时可能自旋。
- 【易错点 2】混淆偏向锁和轻量级锁的获取流程。
- 【易错点 3】忽略自旋的 CPU 消耗,认为自旋总是优于阻塞。