Mark Word是64位JVM中动态切换内容的内存结构,其最后3位(2位锁标志+1位偏向位)决定锁状态:01+biased_lock=0为无锁态,01+1为偏向锁,00为轻量级锁,10为重量级锁;内容覆盖不可逆,升级由竞争触发且单向。

要真正看懂Mark Word,得把它当成一块会“变脸”的内存——同一段64位(64位JVM)空间,根据锁竞争情况动态切换存储内容,而不是死记某个固定结构。
盯住那两位锁标志位和一位偏向位
Mark Word的最后3位是关键开关:最低2位是lock(00、01、10),第3位是biased_lock(0或1)。这三位组合起来,直接决定当前锁状态:
- 01 + biased_lock=0 → 无锁态(存hashCode、GC年龄)
- 01 + biased_lock=1 → 偏向锁(存线程ID、epoch、年龄)
- 00 → 轻量级锁(存指向栈中Lock Record的指针)
- 10 → 重量级锁(存指向堆中Monitor对象的指针)
理解“覆盖”比记住字段更重要
哈希值、线程ID、锁指针都挤在同一个64位里,不可能共存。一旦加锁,原有内容就会被覆盖:
- 对象刚创建时没调用
hashCode(),Mark Word高位空着,低位是01 - 首次调用
System.identityHashCode(),31位哈希值写入高位,低位仍为01 - 进入synchronized块触发偏向锁,哈希值被线程ID+epoch覆盖,再也找不回来
- 升级到轻量级锁,又变成00开头+指针,原内容全丢
锁升级不是自动发生,而是由竞争行为触发
状态切换背后是具体动作,不是时间到了就升级:
立即学习“Java免费学习笔记(深入)”;
- 第一个线程进synchronized → JVM尝试CAS写入自身ID → 成功则进入偏向锁
- 第二个线程来抢同一把锁 → 触发偏向撤销(需一次CAS)→ 升为轻量级锁
- 轻量级锁下自旋10次仍抢不到 → 直接膨胀为重量级锁,线程挂起进Monitor的EntryList
- 所有升级单向不可逆,没有降级机制
验证结构变化最直接的方式是用JOL工具
光看文档容易绕晕,动手打印才清晰:
- 引入JOL依赖后,用
ClassLayout.parseInstance(obj).toPrintable()输出对象头十六进制 - 分别在new对象后、调用hashCode后、synchronized块内执行,对比Mark Word低3位和高位数据变化
- 注意:默认开启偏向锁(-XX:+UseBiasedLocking),如需关闭可加参数验证无锁→轻量过程


















