Monitor概念
Monitor 被翻译为监视器或管程
每个 Java 对象都可以关联一个 Monitor 对象, 如果使用 synchronized 给对象上锁(重量级)之后,该对象头的 Mark Word 中就被设置指向 Monitor 对象的指针
Monitor 结构如下
- 刚开始 Monitor 中 Owner 为 null
- 当 Thread-0 执行 synchronized(object) 上锁就会将 Monitor 的所有者 Owner 置为 Thread-0, 同时对象 object 中的 Mark Word 的 state 也会发生相应改变。
- 在 Thread-0 上锁的过程中,如果 Thread-1, Thread-2, Thread-3 也来执行 synchronized(object), 就会进入 EntryList 变成 BLOCKED 状态
- Thread-0 执行完同步代码块的内容,然后唤醒 EntryList 中等待的线程来竞争锁,竞争时是非公平的
- 图中 WaitSet 中的 Thread-4, Thread-5 是之前获得过锁,但条件不满足进入 WAITING 状态的线程,可以由 notifyAll() , notify() 唤醒
注意:
- synchronized 必须是进入同一个对象的 monitor 才有上述的效果
- 不加 synchronized 的对象不会关联监视器,不遵从以上规则
**Java 对象头 **
以 32 位虚拟机为例
普通对象
|----------------------------------------------------------|
| Object Header (64 bits) |
|----------------------------------------------------------|
| Mark Word (32 bits) | Klass Word (32 bits) |
|----------------------------------------------------------|
Mark Word : 用于存储对象自身的运行时数据, 如哈希码 (HashCode) 、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程ID等。同时考虑到虚拟机的空间效率,Mark Word 被设计成一个有着动态定义的数据结构。
Klass Word: 类型定义信息 , Java 虚拟机通过这个指针来确定该对象是哪个类的实例(并不是所有的虚拟机都必须在对象数据上保留类型指针)。此外,如果对象是一个 Java 数组,那在对象头中还必须有一块用于记录数组长度的数据,因为如果数组的长度是不确定的,将无法推断出数组的大小。
数组对象
|--------------------------------------------------------------------------------------|
| Object Header (96 bits) |
|--------------------------------------------------------------------------------------|
| Mark Word (32 bits) | Klass Word (32 bits) | array length (32bits) |
|--------------------------------------------------------------------------------------|
其中 Mark Word 结构 (动态数据结构)为
存储内容 | 标志位 | 状态 |
---|---|---|
对象哈希码、对象分代年龄 | 01 | 未锁定 |
指向锁记录的指针 | 00 | 轻量级锁定 |
指向重量级锁的指针 | 10 | 膨胀(重量级锁定) |
空,不需要记录信息 | 11 | GC标记 |
偏向线程ID、便向时间戳、对象分代年龄 | 01 | 可偏向 |
32 位虚拟机
|-------------------------------------------------- |-----------------------------------|
| Mark Word (32 bit) | State |
|-------------------------------------------------- |-----------------------------------|
| hashcode:25 | age:4 | biased_block:0 |01 | Normal |
|-------------------------------------------------- |-----------------------------------|
| thread:23 |epoch:2| age:4 | biased_block:1 |01 | Biased |
|-------------------------------------------------- |-----------------------------------|
| ptr_to_lock_record:30 |00 | LightWeight Locked |
|-------------------------------------------------- |-----------------------------------|
| ptr_to_heavyweight_monitor:30 |10 | HeavyWeight Locked |
|-------------------------------------------------- |-----------------------------------|
| |11 | Marked for GC |
|-------------------------------------------------- |-----------------------------------|
64 位虚拟机
|-------------------------------------------------------------|-------------------------|
| Mark Word (64 bit) | State |
|-------------------------------------------------------------|-------------------------|
| unused:25 | hashcode:31 | unused:1 | age:4 | biased_block:0 | 01 | Normal |
|-------------------------------------------------------------|-------------------------|
| thread:23 | epoch:2 | unused:1 | age:4 | biased_block:1 | 01 | Biased |
|-------------------------------------------------------------|-------------------------|
| ptr_to_lock_record:62 | 00 | LightWeight Locked |
|-------------------------------------------------------------|-------------------------|
| ptr_to_heavyweight_monitor:62 | 10 | HeavyWeight Locked |
|-------------------------------------------------------------|-------------------------|
| | 11 | Marked for GC |
|-------------------------------------------------------------|-------------------------|
[深入理解 Java 虚拟机 第三版]: