monitor 概念
管程, 监视器. 在操作系统中, 存在着 semaphore 和 mutex, 即信号量和互斥量, 使用基本的 mutex 进行开发时, 需要小心的使用 mutex 的 down 和 up 操作, 否则容易引发死锁问题. 为了更好的编写并发程序, 在 mutex 和 semaphore 基础上, 提出了更高层次的同步原语, 实际上, monitor 属于编程语言的范畴, C 语言不支持 monitor, 而 java 支持 monitor 机制.
一个重要特点是, 在同一时间, 只有一个线程 / 进程能进入 monitor 所定义的临界区, 这使得 monitor 能够实现互斥的效果. 无法进入 monitor 的临界区的进程 / 线程, 应该被阻塞, 并且在适当的时候被唤醒. 显然, monitor 作为一个同步工具, 也应该提供这样管理线程 / 进程的机制.
monitor 这个机制之所以被称为: 更高级的原语, 它不可避免的需要对外屏蔽这些机制, 并且在内部实现这些机制, 使得 monitor 成为一个简洁易用的借口.
monitor 基本元素
临界区
monitor 对象和锁
条件变量以及定义在 monitor 对象上的 wait,signal 操作
使用 monitor 主要是为了互斥进入临界区, 为了能够阻塞无法进入临界区的进程, 线程, 需要一个 monitor object 来协助, 这个 object 内部会有相应的数据结构, 例如列表, 用来保存被阻塞的线程; 同时由于 monitor 机制本质是基于 mutex 原语的, 所以 object 必须维护一个基于 mutex 的锁.
此外, 为了在适当的时候能够阻塞和唤醒 进程 / 线程, 还需要引入一个条件变量, 这个条件变量用来决定什么时候是 "适当的时候", 这个条件可以来自程序代码的逻辑, 也可以是在 monitor object 的内部, 总而言之, 程序员对条件变量的定义有很大的自主性. 不过, 由于 monitor object 内部采用了数据结构来保存被阻塞的队列, 因此它也必须对外提供两个 API 来让线程进入阻塞状态以及之后被唤醒, 分别是 wait 和 notify.
monitor 在 java 中的实现
临界区的圈定
被 synchronized 关键字修饰的方法, 代码块, 就是 monitor 机制的临界区
monitor object
在上述 synchronized 关键字被使用时, 往往需要指定一个对象与之关联, 例如 synchronized(this), 总之, synchronized 需要管理一个对象, 这个对象就是 monitor object.
monitor 机制中, monitor 我不检测题充当着维护 mutex 和 wait, signalAPI 来管理线程的阻塞和唤醒.
Java 对象存储在内存中, 分别分为三个部分, 即对象头, 实例数据和对齐填充, 而在其对象头中, 保存了锁标识; 同时, java.lang.Object 类定义了 wait(),notify(),notifyAll() 方法, 这些方法的具体实现, 依赖于一个叫 ObjectMonitor 模式的实现, 这是 JVM 内部基于 C++ 实现的一套机制, 基本原理如下所示:
当一个线程需要获取 Object 的锁时, 会被放入 EntrySet 中进行等待, 如果该线程获取到了锁, 成为当前锁的 owner. 如果根据程序逻辑, 一个已经获得了锁的线程缺少某些外部条件, 而无法继续进行下去 (例如生产者发现队列已满或者消费者发现队列为空), 那么该线程可以通过调用 wait 方法将锁释放, 进入 wait set 中阻塞进行等待, 其它线程在这个时候有机会获得锁, 去干其它的事情, 从而使得之前不成立的外部条件成立, 这样先前被阻塞的线程就可以重新进入 EntrySet 去竞争锁. 这个外部条件在 monitor 机制中称为条件变量.
来源: http://www.bubuko.com/infodetail-3217650.html