synchronized 锁升级的过程
在 Java 中锁升级特指synchronized在 JDK 1.6 后引入的优化机制锁状态从无锁逐步升级为偏向锁、轻量级锁、重量级锁且升级方向是单向的不可降级。整个过程基于对象头中的 Mark Word 变化实现。 锁升级的四个阶段锁状态适用场景核心行为Mark Word 内容简略无锁对象刚创建没有线程竞争初始状态哈希码、分代年龄、锁标志位01未偏向偏向锁只有一个线程反复进入同步块记录线程 ID后续该线程重入零开销线程ID 偏向时间戳 标志位01偏向轻量级锁少量线程交替持有锁竞争不激烈自旋等待CAS避免阻塞指向栈中锁记录的指针 标志位00重量级锁多个线程激烈竞争自旋失败或超时线程阻塞依赖操作系统 mutex指向监视器Monitor指针 标志位10⚙️ 升级触发条件详解无锁 → 偏向锁第一个线程进入synchronized块时JVM 通过 CAS 将当前线程 ID 写入对象头。前提JVM 开启了偏向锁默认有延迟可用-XX:BiasedLockingStartupDelay0关闭延迟。偏向锁 → 轻量级锁当第二个线程尝试竞争该偏向锁时偏向锁失效。在全局安全点Safepoint撤销偏向锁若原持有锁的线程已退出则对象头置为无锁再升级为轻量级锁CAS 竞争。若原线程仍存活且持有锁则直接膨胀为轻量级锁原线程持有锁新线程开始自旋。轻量级锁 → 重量级锁自旋超过一定次数JDK 1.6 后为自适应自旋根据历史情况动态调整。自旋过程中又有新的线程加入竞争。持有锁的线程耗时过长自旋浪费 CPU。此时锁膨胀为重量级锁未获得锁的线程全部进入阻塞状态BLOCKED。 注意事项锁升级不可逆一旦升级为重量级锁即使后续无竞争也不会降级。偏向锁在 JDK 15 后默认禁用并废弃高并发下撤销成本过高。哈希码会影响锁升级若对象已调用hashCode()对象头中存储了哈希码则无法进入偏向锁状态直接轻量级锁。批量重偏向当大量对象发生偏向锁撤销时JVM 会批量重偏向或批量撤销避免频繁 Safepoint。 一句话总结无锁 → 偏向锁单线程→ 轻量级锁自旋→ 重量级锁阻塞全部通过 CAS 修改对象头 Mark Word 实现目的是在低竞争时避免操作系统互斥量开销。