锁升级
-
无锁 → 偏向锁
- 条件:只有一个线程进入同步块。
- 表现:JVM 通过 CAS 将线程 ID 记录在对象头中。之后该线程再次进入时,只需要比对 ID 是否一致,无需任何同步操作。
-
偏向锁 → 轻量级锁
- 条件:另一个线程尝试竞争偏向锁。
- 表现:偏向锁被撤销,锁升级为轻量级锁。双方通过 CAS 尝试修改对象头来获取锁,不会让线程阻塞。
-
轻量级锁 → 重量级锁
- 条件:CAS 自旋超过阈值(自旋次数过多)、自旋线程数过多,或者有线程在等待。
- 表现:锁膨胀为重量级锁。未获取到锁的线程会被挂起(阻塞) ,进入等待队列,等待操作系统的唤醒。
锁消除(Lock Elimination)与锁粗化(Lock Coarsening)
- 锁消除:JIT 编译器通过逃逸分析,发现某些同步代码根本不可能被多线程访问,就会直接去掉
synchronized锁。例如,局部变量StringBuffer的append方法(原方法是同步的),若只在方法内部使用,不会被其他线程共享,锁就会被消除。 - 锁粗化:如果 JVM 检测到一系列连续的锁操作(如循环内反复加锁/解锁),会将锁的范围扩大到整个操作序列的外部,减少频繁获取/释放锁带来的性能损耗。