应优先使用 synchronized,因其在jdk 1.6后性能接近lock,且更简洁安全;锁对象需具体明确,避免共享;无需手动干预jvm自动优化的锁策略;优化重点在于减少真实竞争而非锁形态。

Java 中 synchronized 的演进不是为了增加开发者负担,而是让“写对”变得更自然、“写好”更有依据。它从早期的粗放式阻塞,逐步收敛为一套兼顾安全、性能与可维护性的默认机制。对日常编码而言,关键不是追逐底层细节,而是理解演进背后的取舍逻辑,并据此调整习惯。
优先用 synchronized,而不是一上来就换 Lock
JDK 1.6 之后的锁升级机制已大幅收窄 synchronized 与 ReentrantLock 的性能差距;JDK 17+ 偏向锁默认禁用后,轻量级锁在低竞争下开销极小,重量级锁仅在真实高争用时才触发。这意味着:
- 绝大多数临界区(如状态更新、计数器增减、简单资源初始化)用
synchronized完全够用,且更简洁、不易出错 - 除非明确需要
tryLock()、可中断等待、或公平性控制,否则不必主动替换为Lock - 过度使用
Lock反而可能引入unlock()忘记调用、finally 块冗余等新风险
锁对象要具体,避免无意识共享
演进过程中,锁的粒度始终是性能与安全的平衡点。现代 JVM 不再靠“偏向”来迁就模糊锁对象,而是更依赖开发者显式选择:
- 修饰实例方法 → 锁的是
this,适用于真正属于该对象的状态操作 - 修饰静态方法 → 锁的是
Class,适用于全局唯一资源(如单例初始化),但要警惕成为瓶颈 - 同步代码块 → 明确指定锁对象(如
private final Object lock = new Object();),最可控,推荐用于细粒度控制 - 避免用
String、常量、或外部传入对象作锁,易引发意外共享或死锁
不手动干预锁策略,信任 JVM 的自动优化
JDK 15 起偏向锁已废弃,JDK 17 彻底移除;自适应自旋、锁消除、锁粗化等优化均由 JVM 在运行时透明完成。开发者无需、也不应:
- 通过
-XX:+UseBiasedLocking强行启用偏向锁(该参数在 JDK 17+ 已无效) - 为“性能”而刻意拆分或合并同步块——JVM 的锁粗化/消除会比人工更准确
- 在日志或监控中过度关注“当前锁状态”,这属于 JVM 内部实现细节,非 API 行为
- 把锁升级日志当作性能问题证据——它只反映竞争模式,不等于性能瓶颈
关注竞争本质,而非锁形态
演进终点不是消灭锁,而是让锁只在真正需要互斥的地方存在。因此更有效的优化方向是:
- 检查是否真有共享状态:能否用局部变量、不可变对象、ThreadLocal 替代?
- 评估是否必须强一致:读多写少场景,考虑
StampedLock或无锁结构(如ConcurrentHashMap) - 识别伪竞争:逃逸分析可能已帮您消除了锁(如方法内新建对象的同步块)
- 用 JFR 或 async-profiler 观察实际锁争用热点,而非凭经验加锁或去锁
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











