JVM锁消除与锁粗化优化原理
详细解释JVM的锁消除(Lock Elimination)和锁粗化(Lock Coarsening)两种锁优化技术,包括触发条件、实际效果以及如何通过JVM参数控制这些优化。
回答
古法程序员
1. 锁消除(Lock Elimination)
- 原理:逃逸分析确认对象不会逃逸后,消除该对象上的同步操作
- 前提:
-XX:+EliminateLocks(默认开启) - 示例:
// StringBuilder.append是同步的(继承自AbstractStringBuilder)
public String concat(String a, String b) {
StringBuilder sb = new StringBuilder();
sb.append(a); // sb不逃逸,锁被消除
sb.append(b);
return sb.toString(); // toString返回新String,sb仍然未逃逸
}
- 效果:消除冗余的monitorenter/monitorexit指令
2. 锁粗化(Lock Coarsening)
- 原理:将相邻的多个同步块合并为一个更大的同步块
- 触发场景:频繁获取释放锁→膨胀成一次性持有
- 示例:
// 优化前
for (int i = 0; i < 100; i++) {
synchronized (lock) { // 每次循环获取释放锁
sum += i;
}
}
// 优化后
synchronized (lock) { // 一次获取,释放
for (int i = 0; i < 100; i++) {
sum += i;
}
}
- 对比:代码层面手动粗化可帮助JVM做更好的优化
3. 与偏向锁的关系
- 偏向锁是轻量级锁的一种优化(单线程场景消除CAS)
- 锁消除是彻底移除锁,偏向锁是降低锁成本
- JDK 15+默认禁用了偏向锁(
-XX:-UseBiasedLocking)
4. 查看优化
-XX:+PrintCompilation # 查看编译信息
-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining # 查看内联和优化