锁升级、锁消除和锁粗化

5 阅读1分钟

锁升级

  1. 无锁 → 偏向锁

    • 条件:只有一个线程进入同步块。
    • 表现:JVM 通过 CAS 将线程 ID 记录在对象头中。之后该线程再次进入时,只需要比对 ID 是否一致,无需任何同步操作
  2. 偏向锁 → 轻量级锁

    • 条件:另一个线程尝试竞争偏向锁。
    • 表现:偏向锁被撤销,锁升级为轻量级锁。双方通过 CAS 尝试修改对象头来获取锁,不会让线程阻塞
  3. 轻量级锁 → 重量级锁

    • 条件:CAS 自旋超过阈值(自旋次数过多)、自旋线程数过多,或者有线程在等待。
    • 表现:锁膨胀为重量级锁。未获取到锁的线程会被挂起(阻塞) ,进入等待队列,等待操作系统的唤醒。

锁消除(Lock Elimination)与锁粗化(Lock Coarsening)

  • 锁消除:JIT 编译器通过逃逸分析,发现某些同步代码根本不可能被多线程访问,就会直接去掉 synchronized 锁。例如,局部变量 StringBuffer 的 append 方法(原方法是同步的),若只在方法内部使用,不会被其他线程共享,锁就会被消除。
  • 锁粗化:如果 JVM 检测到一系列连续的锁操作(如循环内反复加锁/解锁),会将锁的范围扩大到整个操作序列的外部,减少频繁获取/释放锁带来的性能损耗。