JUC--Monitor锁
JUC–Monitor锁
背景
-
JUC–Monitor锁
-
博主以黑马JUC进行学习
Java对象头
-
Java 对象在堆内存中分为 3 部分:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。其中对象头是实现 Monitor、锁、GC 的关键,不同状态下(普通对象 / 数组对象、是否加锁)结构不同。
- 普通对象头(64位JVM)
区域 大小(64 位) 核心作用 Mark Word(标记字段) 8 字节 存储对象的哈希值、GC 年龄、锁状态、Monitor 指针、偏向锁线程 ID 等核心信息 Klass Pointer(类型指针) 8 字节(默认) 指向对象所属类的元数据(klass),JVM 通过它确定对象的类型(可通过 -XX:+UseCompressedOops压缩为 4 字节)- 数组对象的对象头
区域 大小(64 位) 作用 Mark Word 8 字节 同普通对象 Klass Pointer 8 字节 同普通对象 Array Length 4 字节 存储数组的长度 - Mark Word 的核心状态
锁状态 2bit 锁标志位 Mark Word 存储内容 无锁 01 对象哈希值(31bit) + 分代年龄(4bit) + 是否偏向锁(1bit:0) + 锁标志位(2bit:01) 偏向锁 01 偏向锁线程 ID(54bit) + Epoch(2bit) + 分代年龄(4bit) + 是否偏向锁(1bit:1) + 锁标志位(2bit:01) 轻量级锁 00 指向栈中锁记录的指针(62bit) + 锁标志位(2bit:00) 重量级锁(Monitor) 10 指向 Monitor 对象的指针(62bit) + 锁标志位(2bit:10) GC 标记 11 空(仅锁标志位 11,用于 GC 标记)
Monitor(锁)
- Monitor 被翻译为监视器或管程
- 每个Java 对象都可以关联一个Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的Mark Word 中就被设置指向 Monitor 对象的指针
- 结构
1 | // JVM 底层用 C++ 实现的 ObjectMonitor 核心结构 |
-
例子
-
刚开始 Monitor中的Owner为null
-
当Thread-2执行 synchronized(obj)就会将Monitor的所有者Owner置为Thread-2,Monitor中只能有一个Owner
-
当Thread-2上锁的过程中,如果Thread-3,Thread-4,Thread-5 也来执行 synchronized(obj),就会进入EntryList BLOCKED
-
Thread-2执行完同步代码块的内容,然后唤醒EntryList中等待的线程来竞争锁,竞争是非公平的
注意
- synchronized 必须是进入同一个对象的 monitor 才有上述的效果
- 不加 synchronized 的对象不会关联监视器,不遵从以上规则
-