是的,java中synchronized的自旋仅发生在轻量级锁阶段;重量级锁不自旋,线程直接阻塞。轻量级锁通过cas+自旋尝试获取锁,自旋失败达阈值后才升级为依赖os互斥量的重量级锁。

Java 中 synchronized 在竞争重量级锁时,并不会使用自旋锁 —— 因为一旦升级到重量级锁,线程就直接进入阻塞状态,不再自旋。真正用到自旋锁(包括自适应自旋)的阶段,是轻量级锁竞争失败时、尚未膨胀为重量级锁前的过渡环节。
自旋锁只发生在轻量级锁阶段
当多个线程同时尝试获取同一个已处于轻量级锁状态的对象时,后到达的线程会先执行自旋等待,而不是立刻挂起:
- 自旋本质是空循环(如 while(!isLocked) {}),占用 CPU 时间但避免用户态/内核态切换开销
- 它只在“锁预计很快释放”的前提下有效,比如临界区极短(如简单赋值、计数器++)
- 若自旋期间锁被释放,线程可立即通过 CAS 获取锁,继续执行
- 若自旋超时仍未成功,才触发锁膨胀,升级为重量级锁,线程被操作系统挂起
自适应自旋让等待更聪明
JDK 1.6 引入的自适应机制,让自旋次数不再固定,而是动态调整:
- 如果上次在同一个锁上自旋成功了,且持有锁的线程仍在运行中,本次就多转几圈(比如从10次升到100次)
- 如果多次在该锁上自旋都失败,下次可能直接跳过自旋,一步到位升级为重量级锁
- 判断依据来自 JVM 运行时收集的锁竞争统计信息,属于热点锁的“学习型优化”
重量级锁本身不自旋
重量级锁依赖操作系统互斥量(Mutex),其特点是:
- 线程获取失败后,由 JVM 调用 OS 接口将线程置为 BLOCKED 状态
- 线程放弃 CPU,进入内核等待队列,不消耗 CPU 周期
- 唤醒需经 OS 调度,涉及用户态→内核态→用户态切换,开销大但公平省电
- 此时谈“自旋”已无意义 —— 它是阻塞模型,不是忙等模型
为什么不能对重量级锁自旋?
设计上刻意避免:
- 重量级锁出现意味着竞争已较激烈或临界区较长,自旋大概率白耗 CPU
- 多核环境下,长时间自旋还可能引发其他线程饥饿或调度失衡
- JVM 把“是否值得自旋”的决策权交给轻量级锁阶段,升级即代表放弃自旋策略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











