一、Monitor 原理
1. Monitor 概念
- Monitor,直译为“监视器”,而操作系统领域一般翻译为“管程”,在java领域就是“对象锁”。
- 管程是指管理共享变量以及对共享变量操作的过程,让它们支持并发。翻译成Java领域的语言,就是管理类的状态变量,让这个类是线程安全的。
- synchronized关键字和wait()、notify()、notifyAll()这三个方法是Java中实现管程技术的组成部分。
- Monitor有两大作用:同步和互斥
- wait/notify基于monitor做的,monitor中有owner、entryList、waitSet
- synchronized关联了monitor,是在JVM层面实现的,源码是c++
- ReentrantLock是在java层面实现的类似monitor的作用
JVM第3版对同步指令的描述:
2. java对象 与 Monitor 之间的关系
- 每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象加锁(重量级锁)之后,该 对象头的Mark Word 中就被设置指向Monitor对象 的指针。
Monitor 结构如下
synchronized(obj) {
// 临界区代码
}
- 刚开始 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是非公平锁)
- WaitSet 中的 Thread-0,Thread-1 是之前获得过锁的线程,此时的状态是 WAITING 状态,后面讲wait-notify 时会分析
注意:
- synchronized 必须是进入同一个对象的 monitor 才有上述的效果
- 不加 synchronized 的对象不会关联 monitor ,不遵从以上规则
3.分析OpenJDK源码和C++源码中的Monitor
- 在HotSpot虚拟机中,monitor是通过ObjectMonitor实现的,OpenJDK中对应的源码是ObjectMonitor.java
- C++中对应的源码是ObjectMonitor.cpp、ObjectMonitor.hpp
ObjectMonitor.java 源码:
public class ObjectMonitor extends VMObject {
public ObjectMonitor(Address addr) {
super(addr);
}
}
ObjectMonitor.cpp 源码引入了ObjectMonitor.hpp头文件:
#include "runtime/ObjectMonitor.hpp"
ObjectMonitor.hpp 源码: