synchronized 锁升级原理
从 JDK 1.5 到 JDK 21,synchronized 经历了从”性能杀手”到”首选锁”的逆袭。它的进化背后,是 JVM 对锁优化的极致追求。
一、synchronized 的三种形式
- 1.1 修饰普通方法——锁当前实例
- 1.2 修饰静态方法——锁 Class 对象
- 1.3 修饰代码块——锁指定对象
- 1.4 字节码层面:
ACC_SYNCHRONIZED标志 vsmonitorenter/monitorexit
二、Monitor 机制——重量级锁的底层
- 2.1 ObjectMonitor 结构:
_owner/_EntryList/_WaitSet - 2.2
wait()/notify()/notifyAll()与 Monitor 的交互 - 2.3 为什么早期的 synchronized 很重——内核态切换
三、偏向锁——无竞争的优化
- 3.1 偏向锁的设计初衷——大部分锁从始至终只有一个线程竞争
- 3.2 Mark Word 中偏向锁的标记位
- 3.3 偏向锁的获取与撤销过程
- 3.4 偏向锁的批量重偏向与批量撤销
- 3.5 JDK 15 默认关闭偏向锁、JDK 21 彻底移除
四、轻量级锁——自旋的优雅
- 4.1 轻量级锁的加锁过程——CAS 替换 Mark Word
- 4.2 Lock Record 与 Displaced Mark Word
- 4.3 自旋等待——自适应自旋
- 4.4 轻量级锁膨胀为重量级锁的条件
五、锁膨胀的完整路径
- 5.1 无锁 → 偏向锁 → 轻量级锁 → 重量级锁
- 5.2 不可降级的单向膨胀
- 5.3 每个阶段的触发条件
六、锁消除与锁粗化
- 6.1 锁消除——逃逸分析的应用
- 6.2 锁粗化——连续加锁解锁的合并优化
- 6.3 实际代码中的例子
七、synchronized vs ReentrantLock 的正确选择
- 7.1 性能对比(JDK 6 前后差异巨大)
- 7.2 功能对比——中断、超时、公平锁、多条件变量
- 7.3 什么时候用 synchronized,什么时候用 Lock
八、总结
- synchronized 的核心优化思想
- 日常开发中应该如何正确使用
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!