Mark Word是Java对象头中动态复用的64位内存区域,依锁状态切换存储内容:无锁态(01+biased_lock=0)存hashcode、GC年龄;偏向锁(01+biased_lock=1)存线程ID与epoch;轻量级锁(00)存指向栈中Lock Record的指针;重量级锁(10)存指向堆中Monitor的指针。

Java对象头里的Mark Word,是理解synchronized锁行为的核心。它不是固定结构,而是一块“动态寄存器”,根据锁竞争情况实时切换存储内容——本质上是用同一段64位内存,复用不同字段表达不同状态。关键不在于记住了几个名词,而在于看清三位标志位(lock + biased_lock)如何组合驱动状态迁移。
无锁态:空闲但有准备
标志位为 01,且偏向位为 0。此时Mark Word主要存三样东西:31位identity_hashcode(未被调用时为空)、4位GC分代年龄、以及保留位。注意:hashCode不是对象一创建就计算好,而是首次调用System.identityHashCode()或参与哈希容器时才生成并写入;一旦后续加锁,这部分空间会被覆盖,hashCode会转移到Monitor中暂存。
偏向锁:单线程的“熟人特权”
标志位仍是 01,但偏向位变为 1。此时Mark Word腾出54位存持有线程ID,2位存epoch(用于批量撤销),4位仍为年龄。它的本质是“一次CAS换长期免检”:第一个线程进入synchronized块时,JVM尝试用CAS把自身ID写入Mark Word;成功后,该线程后续再进同一把锁,连CAS都不用做,直接通过比对线程ID放行。只要没别的线程来抢,它就一直保持这个状态。
轻量级锁:多线程下的自旋博弈
标志位变成 00,偏向位失效。此时Mark Word不再存线程ID,而是存一个62位指针,指向当前持有锁的线程栈帧里的Lock Record。每个线程在尝试获取锁时,先在自己栈上新建一条Lock Record,复制原Mark Word内容进去,再用CAS把Mark Word替换成指向自己的指针。成功者获得锁;失败者开始自旋等待——不是死等,而是循环检测Mark Word是否已恢复为无锁态或被其他线程替换。自旋次数默认上限为10次,超限即触发升级。
重量级锁:操作系统介入的最终防线
标志位升为 10,Mark Word存的是62位指针,指向堆中一个真正的Monitor对象。这时锁的控制权交给了操作系统互斥量(mutex),线程竞争失败后不再自旋,而是挂起进入阻塞队列(EntryList)。Monitor内部有Owner、EntryList、WaitSet三部分,支持wait/notify机制。重量级锁开销最大,但能保证高竞争下的公平性与稳定性——它是锁升级的终点,不可逆。











