自旋锁仅在多核下有效,因单核无法并行执行持锁与自旋线程,导致空转浪费;多核则允许二者分核运行,配合CAS原子操作和自适应策略,在短临界区、低竞争场景下以忙等换低延迟。

轻量级锁在多核处理器下的自旋优化,核心是用“忙等换阻塞”,在锁持有时间短、竞争不激烈时,避免线程挂起/唤醒的开销,提升吞吐效率。
自旋为什么只在多核下有效
单核 CPU 上,一个线程持有锁执行同步块时,另一个自旋线程无法真正并发运行——它会抢占不到 CPU 时间片,只能空转等待,白白消耗资源。而多核环境下,持有锁的线程和自旋等待的线程可以分别在不同核心上并行执行:锁持有者完成临界区后释放锁,自旋线程几乎立刻能检测到并抢到锁,无需陷入内核态调度。
CAS 是自旋重试的原子基础
每次自旋都依赖一次 CAS 操作尝试修改对象头 Mark Word:
- V(当前值):读取对象头中最新的 Mark Word
- A(期望值):判断是否仍为“无锁态”(如最后两位为 01)或“自己持有的轻量级锁”(用于重入)
- B(新值):若成功,写入指向本线程栈中 Lock Record 的指针,状态位设为 00
失败不等于放弃——只要 V ≠ A,就说明锁状态已变,需重新读取再试;只有连续多次失败,才考虑升级。
立即学习“Java免费学习笔记(深入)”;
自适应自旋动态调优次数
JDK 6 起默认启用自适应机制,不再固定循环 10 次,而是根据历史表现动态调整:
- 同一把锁上次自旋成功了 → 本次允许更多轮次,提高抢到概率
- 锁持有者线程仍在运行(非被挂起)→ 更倾向继续自旋,因释放锁可能性高
- 最近几次都失败 → 缩短自旋周期,更快让出 CPU,升级为重量级锁走阻塞队列
这种策略让自旋从“盲目忙等”变成“有依据的等待”,兼顾响应速度与 CPU 利用率。
自旋不是万能,超阈值必须升级
自旋本质是用 CPU 时间换低延迟,但存在硬约束:
- JVM 设置默认上限(如 -XX:PreBlockSpin=10),可调但不宜过大
- 持续自旋失败说明竞争真实存在,此时膨胀为重量级锁,将等待线程挂入 Monitor 队列,由操作系统调度唤醒
- 一旦升级,该对象后续加锁直接走重量级路径,不再尝试轻量级锁
升级不是性能倒退,而是权衡结果:当等待成本超过调度开销时,阻塞反而更经济。


















