锁消除和锁粗化是JVM JIT编译器自动执行的运行时优化:锁消除基于逃逸分析移除无竞争的锁,锁粗化合并连续小粒度锁以减少开销;二者均需C2编译、热点代码触发,且锁消除依赖-XX:+DoEscapeAnalysis与-XX:+EliminateLocks同时启用。

锁消除和锁粗化是 JVM 在运行时自动完成的优化,不需要手动“配置”代码逻辑,但要让它们生效,得满足 JVM 的启动条件和运行环境要求。
锁消除必须开启逃逸分析
锁消除依赖逃逸分析判断对象是否线程私有。JDK8 及以后默认开启,但建议显式确认:
- -XX:+DoEscapeAnalysis:启用逃逸分析(JDK8+ 默认开,但某些定制版或容器环境可能关闭)
- -XX:+EliminateLocks:启用锁消除(必须与逃逸分析同时开启,否则无效)
- 避免让局部对象“逃逸”:不赋值给 static 字段、不传入未知方法(如 logger.info(obj))、不放入 HashMap/ConcurrentLinkedQueue 等共享容器
锁粗化对参数没额外开关,但有执行前提
锁粗化无需单独 JVM 参数,只要满足以下条件,C2 编译器就会自动合并相邻同步块:
- 同一对象被连续多次加锁(例如循环内反复 synchronized(lock) {...})
- 中间没有异步操作、无分支跳转、无其他线程可见的共享状态变更
- 代码已进入 JIT 热点编译阶段(不是刚启动或低频调用的冷代码)
确保进入 C2 编译器优化路径
这两个优化只在 server 模式下、由 C2 编译器触发,解释执行或 C1 编译不会生效:
立即学习“Java免费学习笔记(深入)”;
- 使用 -server(JDK8+ 通常默认,但嵌入式或精简版可能需显式指定)
- 让目标方法被高频调用(例如循环执行 ≥10 万次),促使 JIT 将其识别为热点方法
- 可加 -XX:+PrintCompilation 观察方法是否被 C2 编译(输出含 “C2” 标记)
验证是否生效的小技巧
光看代码无法确定优化是否发生,实际验证更可靠:
- 对比 StringBuffer 和 StringBuilder 在单线程场景下的性能差异——若两者耗时接近,说明 StringBuffer 的锁已被消除
- 用 JMH 写基准测试,开启 -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly(需 hsdis)查看汇编,确认 monitor 指令是否消失或合并
- 禁用逃逸分析(-XX:-DoEscapeAnalysis)后性能明显下降,反向印证锁消除在起作用


















