锁升级由竞争模式变化触发:偏向锁在出现多线程竞争时撤销并升级为轻量级锁;轻量级锁自旋失败后膨胀为重量级锁,此时性能断崖式下降。

锁升级到底在什么时候发生
Java 的 synchronized 锁升级(偏向锁 → 轻量级锁 → 重量级锁)不是按时间或调用次数触发的,而是由**竞争模式变化**决定的。当一个线程持有偏向锁后,另一个线程尝试进入同一同步块,JVM 就会撤销偏向锁并升级为轻量级锁;若轻量级锁自旋失败(比如自旋耗时超阈值、CPU 核心数不足、或自旋中被挂起),就会膨胀成重量级锁——这才是性能断崖的起点。
常见错误现象:java.lang.Thread.State: BLOCKED (on object monitor) 大量出现,jstack 输出里看到一堆线程卡在同一个 synchronized 方法入口,说明已经落到重量级锁层面。
- 偏向锁默认开启(JDK 6–8),但高竞争场景下它反而增加撤销开销,建议生产环境用
-XX:-UseBiasedLocking关掉 - 轻量级锁的自旋次数由
-XX:PreBlockSpin(旧版)或更智能的自适应策略控制,不建议硬调;重点应放在减少竞争本身 - 锁升级不可逆:一旦升级到重量级锁,该对象监视器后续所有同步操作都走操作系统互斥量,开销陡增
业务逻辑拆分的关键判断点
不是所有 synchronized 块都该拆,要看它是否同时承担「状态保护」和「业务耗时」两种职责。典型反例是把数据库查询、HTTP 调用、JSON 序列化全塞进一个 synchronized 方法里——锁住的不是临界资源,而是整个业务流程。
使用场景:订单创建接口中需保证用户余额扣减原子性,但订单号生成、日志记录、消息投递等环节与余额无关。
立即学习“Java免费学习笔记(深入)”;
- 只对真正共享且可变的状态加锁,例如
userBalanceMap.put(userId, newBalance),而不是整个createOrder()方法 - 把耗时操作(如
httpClient.post()、objectMapper.writeValueAsString())移出同步块,哪怕需要提前计算好参数再传入 - 避免在锁内做任何可能阻塞的操作:I/O、锁等待(嵌套 synchronized)、甚至
System.currentTimeMillis()(虽快但非零成本)
替代 synchronized 的轻量方案选型
不是所有临界区都需要 JVM 监视器。如果只是计数、开关、单次初始化,AtomicInteger、AtomicBoolean、AtomicReference 几乎零成本;如果是多字段协同更新,才考虑 ReentrantLock 或更细粒度的分段锁。
性能影响:一个 AtomicInteger.incrementAndGet() 在无竞争时是单条 CPU 指令(CAS),比最轻量的偏向锁还快;而 ReentrantLock 虽支持可中断、超时,但每次 lock()/unlock() 都有额外方法调用和状态检查开销。
- 计数类场景优先用
AtomicLong,别用synchronized(this) { count++; } - 初始化单例用
Double-Checked Locking+volatile字段,比直接 synchronized 方法更准、更省 - 如果必须用锁,且临界区较短、竞争中等,
ReentrantLock的公平性参数(new ReentrantLock(true))反而会恶化吞吐,保持默认非公平即可
容易被忽略的隐式锁竞争
看似没写 synchronized,但某些 JDK 类内部用了全局锁,比如 SimpleDateFormat 的 parse()、HashMap 在扩容时的并发修改检测、甚至 String.substring()(JDK 7u6 之前)都可能引发意外争用。
常见错误现象:压测时 QPS 上不去,但 synchronized 块极少,jstack 却显示线程在 sun.text.normalizer.NormalizerBase 或 java.util.HashMap.resize() 等位置 BLOCKED。
-
SimpleDateFormat必须每个线程私有,或改用线程安全的DateTimeFormatter -
HashMap不要在线程间共享可写实例;高频读写场景用ConcurrentHashMap,但注意它的size()不是 O(1),computeIfAbsent()可能重复计算 - 日志框架如 Log4j2 默认异步,但若手动用了
Logger.getLogger()+ 静态变量,且在类加载期初始化,也可能引入类初始化锁竞争
真正难处理的从来不是怎么加锁,而是发现哪些地方“悄悄”在抢同一把锁。线程 dump 和锁竞争热点分析比盲目优化同步块更有价值。











