Mark Word 是 Java 对象头中动态复用的内存区域,64 位 JVM 占 8 字节,其内容由 lock 标志位(00/01/10)和 biased_lock 位共同驱动:无锁态存 identity_hashcode 和 GC 年龄;偏向锁态存线程 ID 和 epoch;轻量级锁态存指向栈中 Lock Record 的指针;重量级锁态存指向堆中 Monitor 的指针;锁升级单向不可逆。

Mark Word 是 Java 对象头中一块动态复用的内存区域,64 位 JVM 下占 8 字节(32 位 JVM 占 4 字节),它不固定存储某类数据,而是根据对象当前的锁状态实时切换内容。理解它的关键,不是背字段长度,而是抓住“三位控制位”如何驱动状态变化——最后 2 位是 lock 标志位(00、01、10),倒数第 3 位是 biased_lock 偏向位(0 或 1)。这三位组合决定了 Mark Word 存什么、怎么用。
无锁状态:空着但有准备
标志位为 01,且 biased_lock = 0。此时 Mark Word 主要存放:
- 31 位 identity_hashcode(首次调用 System.identityHashCode() 才写入,之前为空)
- 4 位 GC 分代年龄(范围 0–15)
- 其余位用于对齐或保留
注意:hashCode 是延迟计算的;一旦后续加锁,这部分空间立刻被覆盖,原哈希值会转移到 Monitor 中暂存。
偏向锁状态:单线程的“免检通道”
标志位仍为 01,但 biased_lock = 1。此时 Mark Word 腾出约 54 位存线程 ID,2 位存 epoch(用于批量撤销),4 位仍为年龄字段。
立即学习“Java免费学习笔记(深入)”;
本质是一次 CAS 换长期免检:首个线程进入 synchronized 块时,JVM 尝试将自身 ID 写入 Mark Word;成功后,该线程后续再进同一把锁,只需比对线程 ID 即可通行,完全跳过同步操作。
轻量级锁状态:栈上指针的自旋竞争
标志位变为 00,biased_lock 失效。Mark Word 改存一个 62 位指针,指向当前线程栈帧中的 Lock Record。
- 每个竞争线程在自己栈上新建 Lock Record,并复制原 Mark Word 内容
- 用 CAS 尝试将 Mark Word 替换为指向该 Lock Record 的指针
- 失败者进入自旋(默认最多 10 次),循环检测 Mark Word 是否恢复无锁或已被其他线程占用
重量级锁状态:操作系统接管阻塞
标志位升为 10,Mark Word 存 62 位指针,指向堆中真实的 Monitor 对象。
Monitor 包含 Owner(持锁线程)、EntryList(阻塞队列)、WaitSet(等待队列),支持 wait/notify。此时线程竞争失败后不再自旋,而是挂起进入操作系统互斥量(mutex),发生用户态到内核态切换,开销最大。
锁升级由竞争行为触发,单向不可逆:无锁 → 偏向锁 → 轻量级锁 → 重量级锁。没有降级机制,也没有自动回退。


















