轻量级锁的lock record存于当前线程的虚拟机栈帧中;它包含displaced_mark_word(备份原mark word)和隐式owner指针,对象头mark word则通过cas被替换为指向该栈内lock record的指针。

Java 中 synchronized 升级为轻量级锁时,并不是直接在对象头里“保存锁记录”,而是将当前线程的栈帧中的锁记录(Lock Record)地址,通过 CAS 原子操作写入对象头的 Mark Word 中,从而标记该对象已被轻量级锁定。
轻量级锁的锁记录存在哪?
锁记录(Lock Record)是 JVM 在当前线程的虚拟机栈中动态分配的一块内存空间,属于栈帧的一部分。它包含两个关键字段:
- displaced_mark_word:存放对象原本的 Mark Word 内容(即加锁前的状态,如是否偏向、哈希码、分代年龄等);
- owner 指针(隐式):指向当前持有锁的线程栈帧中的该 Lock Record 地址(JVM 通过指针关联,不显式存储)。
对象头如何参与轻量级锁过程?
对象头中的 Mark Word 在轻量级锁状态下会被修改为指向当前线程栈中 Lock Record 的指针(即指向 displaced_mark_word 所在位置的起始地址)。这个过程依赖 CAS:
- 线程尝试获取锁时,先在自己的栈中创建 Lock Record,并把对象原 Mark Word 复制到 displaced_mark_word 字段;
- 然后用 CAS 将对象头的 Mark Word 替换为指向该 Lock Record 的指针;
- CAS 成功 → 锁获取成功,进入轻量级锁定状态;
- CAS 失败 → 说明有其他线程已抢先加锁或发生竞争,可能触发锁膨胀(升级为重量级锁)。
为什么能用对象头存指针?
64 位 JVM 默认开启指针压缩(-XX:+UseCompressedOops),对象头中 Mark Word 为 64 位,但实际用于存储锁信息的低几位(如最后 2–3 位)被定义为锁标志位(biased_lock、lightweight_locked、heavyweight_locked 等)。当标记为轻量级锁(例如 lock bit = 01),剩余高位就可安全存储一个指向栈内 Lock Record 的指针(需保证地址对齐,通常按 8 字节对齐,低位可用作标志)。
锁释放时怎么恢复?
释放轻量级锁时,JVM 会以 CAS 方式将 Lock Record 中的 displaced_mark_word 写回对象头 Mark Word:
- 若 CAS 成功 → 锁释放完成,对象回到无锁状态;
- 若 CAS 失败 → 说明期间有其他线程尝试获取锁并触发了锁升级(比如膨胀为重量级锁),此时需协助唤醒阻塞队列中的线程。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











