轻量级锁会自旋,即当CAS加锁失败时,线程先自旋重试以避免挂起,自旋超阈值后升级为重量级锁。

Java 中的轻量级锁(Lightweight Locking)并不是一个独立的锁类型,而是 JVM 在 synchronized 关键字实现中采用的一种优化机制,用于在无竞争或低竞争场景下避免直接进入操作系统互斥量(Mutex),从而减少线程挂起/唤醒开销。它本质上是偏向锁、轻量级锁、重量级锁三级锁升级策略中的中间阶段,核心依赖于对象头中的 Mark Word 和 CAS 操作。
轻量级锁的触发与工作原理
当一个线程尝试获取 synchronized 锁时,若对象未被锁定(Mark Word 处于“无锁”状态),JVM 会尝试使用 CAS 将当前线程的栈帧地址写入对象头的 Mark Word。若成功,即表示轻量级锁获取成功;若失败(说明已有其他线程持有锁),则触发锁膨胀流程。
- 轻量级锁加锁过程不涉及 OS 级线程阻塞,仅依赖 CPU 原子指令,开销远低于重量级锁
- 锁记录(Lock Record)保存在线程栈中,用于后续解锁时恢复 Mark Word
- 一旦有第二个线程尝试竞争同一把锁,JVM 会尝试自旋等待(Spin Lock),但自旋失败后将升级为重量级锁
轻量级锁与“轻量级竞争条件”的区别
需注意:“轻量级锁”是 JVM 的内部锁优化机制,而所谓“轻量级竞争条件”并非 Java 标准术语,实际常指在低并发场景下,开发者通过非阻塞手段(如 volatile、CAS、AtomicXXX)避免使用 synchronized 或 ReentrantLock 来处理共享状态更新,从而规避锁开销。
- volatile 适用于状态标记(如 running = false)、单次写+多次读的简单场景,但不保证复合操作原子性
- AtomicInteger.incrementAndGet() 等方法基于 Unsafe CAS 实现,适合计数器类场景,比 synchronized 更轻量
- LongAdder 在高并发累加场景下比 AtomicLong 更高效,通过分段热点降低 CAS 冲突
何时该用轻量级锁?何时该绕过它?
轻量级锁由 JVM 自动启用,开发者无需显式控制。是否“受益”取决于实际竞争模式:
立即学习“Java免费学习笔记(深入)”;
- 适合:临界区极短(如几行赋值)、线程交替执行、极少发生竞争(如单线程反复进入同步块)
- 不适合:存在真实竞争且持续时间稍长——自旋浪费 CPU,最终仍要膨胀为重量级锁
- 更优替代:若逻辑本身可无锁化(如用 ConcurrentHashMap 替代 Hashtable + synchronized),优先选择 lock-free 数据结构
验证与调优建议
可通过 JVM 参数观察锁升级行为:
- -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 可间接反映锁竞争导致的 GC 压力变化
- -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly(配合 hsdis)可查看 synchronized 编译后的锁指令序列
- JFR(Java Flight Recorder)中 Monitor Blocked Time 和 Locked Ownable Synchronizers 事件可定位真实锁瓶颈
不复杂但容易忽略:轻量级锁的价值高度依赖于应用访问模式,盲目追求“无锁”可能引入 ABA 或内存可见性问题;合理使用 synchronized + JVM 默认优化,往往比手写 CAS 更安全、更易维护。


















