synchronized用的锁是存在Java对象头里的。如果对象是数组类型,则虚拟机用3个字宽(Word)存储对象头,如果对象是非数组类型,则用2字宽存储对象头。在32位虚拟机中,1字宽等于4字节,即32bit,如表所示。
长度 | 内容 | 说明 |
---|---|---|
32/64bit | Mark Word | 存储对象的 hashCode 或锁信息等 |
32/64bit | Class Metadata Address | 存储到对象类型数据的指针 |
32/64bit | Array length | 数组的长度 (如果当前对象是数组) |
Java对象头里的Mark Word里默认存储对象的HashCode、分代年龄和锁标记位。32位JVM的Mark Word的默认存储结构如表所示。
锁状态 | 25bit | 4bit | 1bit 是否偏向锁 | 2bit 锁标志位 |
---|---|---|---|---|
无锁状态 | 对象的 hashCode | 对象分代年龄 | 0 | 01 |
在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。Mark Word可能变化为存储以下4种数据,如表所示。
锁状态 | 25bit | 4bit | 1bit | 2bit | |
---|---|---|---|---|---|
23bit | 2bit | 是否偏向锁 | 锁标志位 | ||
轻量级锁 | 指向栈中锁记录的指针 | 00 | |||
重量级锁 | 指向互斥(重量级锁)的指针 | 10 | |||
GC 标记 | 空 | 11 | |||
偏向锁 | 线程 ID | Epoch | 对象分代年龄 | 1 | 01 |
在64位虚拟机下,Mark Word是64bit大小的,其存储结构如表所示。
锁状态 | 25bit | 31bit | 1bit | 4bit | 1bit | 2bit |
---|---|---|---|---|---|---|
cms_free | 分代年龄 | 偏向锁 | 锁标志位 | |||
无锁 | unused | hashcode | 0 | 01 | ||
偏向锁 | TheadId(54bit) | Epoch(2bit) | 1 | 01 |
参考: 方腾飞,魏鹏,程晓明 著. 《Java并发编程的艺术 》(Java核心技术系列)