轻量级锁通过cas在用户态抢锁并自旋重试,避免线程挂起;成功则直接执行,失败则自适应自旋后升级为重量级锁。

轻量级锁通过 CAS 操作在用户态完成抢锁,不进入内核态挂起线程,从而避免阻塞。它的核心不是“完全不阻塞”,而是在锁持有时间短、竞争不激烈时,用自旋重试代替挂起,大幅减少上下文切换开销。
对象头检查与锁记录准备
线程尝试进入 synchronized 块时,JVM 先读取对象头的 Mark Word,确认是否处于无锁状态(标志位为 01)。若是,就在当前线程的栈帧中分配一块「锁记录」空间,把对象原来的 Mark Word 复制进去,为后续 CAS 替换做准备。
CAS 替换 Mark Word 实现快速加锁
线程调用底层 CAS 指令,尝试将对象头的 Mark Word 原子性地替换为指向本线程锁记录的指针:
- 成功 → 锁获取完成,线程继续执行,全程无阻塞、不进等待队列、不触发调度;
- 失败 → 说明已有其他线程占用了该锁,此时不立即挂起,而是转入自旋阶段。
自旋等待 + 自适应阈值控制挂起时机
自旋期间,线程持续用 CAS 检查对象头是否已恢复为无锁状态(或被释放),一旦检测到可抢锁机会,立刻再次尝试 CAS 获取。
- 自旋不是无限进行,JVM 会根据历史竞争情况动态调整自旋次数(自适应自旋);
- 超过阈值后仍未成功,才升级为重量级锁,让线程真正挂起并进入 Monitor 队列;
- 这种“延迟挂起”策略,把昂贵的线程状态切换留给了真正需要的场景。
关键依赖:CAS 的原子性与硬件支持
CAS 操作由 CPU 提供的原子指令(如 x86 的 cmpxchg)保障,确保“比较+交换”不可分割:
- JVM 通过 Unsafe.compareAndSwapObject 等本地方法调用该指令;
- 即使多个线程同时争抢,也只有一个能成功更新 Mark Word,其余线程仅需重试或退让;
- 整个过程不涉及锁的申请/释放逻辑,也没有唤醒机制,天然规避了阻塞路径。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











