从 JDK 1.5 到 JDK 21,synchronized 经历了从”性能杀手”到”首选锁”的逆袭。它的进化背后,是 JVM 对锁优化的极致追求。

一、synchronized 的三种形式

  • 1.1 修饰普通方法——锁当前实例
  • 1.2 修饰静态方法——锁 Class 对象
  • 1.3 修饰代码块——锁指定对象
  • 1.4 字节码层面:ACC_SYNCHRONIZED 标志 vs monitorenter/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 的核心优化思想
  • 日常开发中应该如何正确使用