Skip to content

JVM对Synchronized的优化

一、是什么?
JVM对synchronized的优化是一系列降低锁性能开销的技术,通过锁升级机制(偏向锁→轻量级锁→重量级锁)和运行时策略(如锁消除/粗化),在保证线程安全的同时减少同步操作的开销。这些优化主要在JDK 6+中实现。


1. 偏向锁(Biased Locking)

一、是什么?
JDK 6引入,假设锁总被同一线程访问,首次获取时记录线程ID,后续该线程无需加锁操作。
二、解决什么问题
消除无竞争场景下的锁开销(如单线程重复获取锁)。
三、核心流程

  • 首次加锁:CAS将线程ID写入对象头
  • 重入:检查线程ID匹配直接执行
  • 竞争发生:升级为轻量级锁
    四、应用场景
    单线程重复访问同步块的场景(如循环内的同步)。
    五、注意事项
  • JDK 15后默认禁用(-XX:-UseBiasedLocking),因现代应用多线程竞争激烈
  • 可通过-XX:BiasedLockingStartupDelay=0关闭延迟启用

2. 轻量级锁(Lightweight Locking)

一、是什么?
通过CAS自旋替代OS互斥锁,线程在栈帧创建锁记录(Lock Record),尝试用CAS将对象头替换为指向锁记录的指针。
二、解决什么问题
降低短时锁竞争场景的线程阻塞开销(如两个线程交替执行)。
三、核心流程

  1. 拷贝对象头到栈帧(Displaced Mark Word)
  2. CAS将对象头指向锁记录
  3. 成功:获得锁;失败:自旋或升级
    四、应用场景
    低竞争、同步代码执行快的场景(如瞬时状态更新)。
    五、注意事项
  • 自旋会消耗CPU,超过阈值(-XX:PreBlockSpin)升级重量级锁
  • 适用于锁持有时间<线程切换耗时的场景

3. 重量级锁(Heavyweight Locking)

一、是什么?
传统互斥锁,通过OS的mutex实现,未获锁线程进入阻塞队列。
二、解决什么问题
高竞争场景下的线程调度(如百级线程争抢资源)。
三、核心机制

  • 对象头指向操作系统互斥量(mutex)
  • 竞争线程进入_cxq队列等待唤醒
    四、应用场景
    高并发竞争场景(如秒杀系统核心资源)。
    五、注意事项
  • 线程阻塞/唤醒涉及内核态切换,开销最大
  • JDK 6后通过适应性自旋减少直接阻塞

4. 锁消除(Lock Elimination)

一、是什么?
JIT编译器通过逃逸分析移除不可能存在竞争的锁。
二、解决什么问题
消除无意义的同步开销(如局部对象锁)。
三、触发条件
对象未逃逸出当前线程(如方法内私有锁)。
四、Java示例

java
public void safeMethod() {
    // 局部对象不会逃逸,锁被消除
    Object localLock = new Object();
    synchronized(localLock) { 
        System.out.println("Lock eliminated");
    }
}

五、注意事项

  • 依赖JVM逃逸分析(默认开启)
  • 需服务器模式运行(-server

5. 锁粗化(Lock Coarsening)

一、是什么?
将相邻的同步块合并为单个更大范围的锁。
二、解决什么问题
减少频繁加锁/解锁的开销(如循环内同步)。
三、Java示例

java
// 优化前:100次加锁
for (int i = 0; i < 100; i++) {
    synchronized(lock) { /* 操作 */ }
}

// 优化后:1次加锁
synchronized(lock) {
    for (int i = 0; i < 100; i++) { /* 操作 */ }
}

四、应用场景
循环体内同步或连续同步代码块。


其他关键优化

  • 适应性自旋(Adaptive Spinning)
    根据历史自旋成功率动态调整自旋次数,避免CPU空转。
  • 锁膨胀(Inflation)
    轻量级锁竞争失败时,通过ObjectMonitor转为重量级锁。

锁升级流程总结


注意事项

  1. 锁升级不可逆:重量级锁无法降级
  2. 性能权衡
    • 低竞争:偏向锁/轻量级锁
    • 高竞争:直接重量级锁(避免多次升级开销)
  3. 监控工具
    • JOL(Java Object Layout)分析对象头
    • JFR(Java Flight Recorder)监控锁竞争

总结

优化技术目标场景JDK版本性能影响
偏向锁单线程重复访问6+无竞争时零开销
轻量级锁低竞争短时操作6+CAS自旋消耗CPU
锁消除线程私有锁6+完全消除同步开销
锁粗化连续同步块/循环6+减少锁操作次数
适应性自旋中等竞争6+减少线程阻塞

💡 实践建议:在超高并发场景(如QPS>10k),考虑ReentrantLock替代synchronized,因其提供更灵活的锁控制(可中断、公平锁、条件变量)。