监视器(Monitors)- Java 同步的基本思想
原文地址:http://www.programcreek.com/2011/12/monitors-java-synchronization-mechanism/
如果你在大学时学习了操作系统这门课程,你可能会记得,监视器是操作系统中同步的重要概念。 其实它也用于 Java 同步。 这个文章将用一个比喻来解释“监视器”的基本思想。
1. 什么是监视器?
监视器可以视为一个包含特殊房间的建筑物。 特殊的房间一次只能由一个客户(线程)占用,房间通常包含一些数据和代码。

如果客户想要占用特殊的房间,他必须先进入走廊(Entry Set)等待,然后调度程序将根据一些标准(例如 FIFO)选择其中一个进入。 如果他由于某种原因被暂停,他将被送到等候室,并计划在之后重新进入特殊的房间。 如上图所示,该建筑有 3 间客房。

简而言之,监视器是监视线程访问特殊房间的设施。 它确保只有一个线程可以访问受保护的数据或代码。
2. 如何在 Java 中实现它?
在 Java 虚拟机中,每个对象和类都与监视器逻辑关联。 为了实现监视器的互斥能力,锁(有时称为互斥)与每个对象和类相关联。 这在操作系统书籍中被称为信号量,互斥是二进制信号量。
如果一个线程锁住了某些数据,那么没有其他人可以再获得该锁,直到拥有该锁的线程释放它为止。 如果我们在进行多线程编程时一直繁琐的写一个信号量,这将是极其不方便的。 幸运的是,JVM 可以自动为我们做这些事。
如果要声明一个监视区域,这意味着数据不能被多个线程访问,Java 提供了同步语句和同步方法。 一旦代码嵌入了 synchronized 关键字,它就是一个监视器区域, 而其中的锁由 JVM 自动实现。
3. 在 Java 同步的代码中,哪个部分是监视器?
我们知道每个对象/类都与一个监视器相关联。 所以我认为每个对象都有一个监视器是很好的,因为每个对象可以有自己的关键部分,并能够监视线程序列。
为了让不同线程之间可以协作,Java 提供了 wait() 和 notify() 方法来挂起一个线程,并唤醒另一个正在等待此对象的线程。 另外还有其他 3 个方法:
wait(long timeout, int nanos)
wait(long timeout) notified by other threads or notified by timeout.
notify(all)
以上方法只能在 synchronized 语句或 synchronized 方法中调用。 因为如果一种方法不需要互斥,则不需要在线程之间监视或协作,每个线程都可以自由地访问该方法。
感兴趣的话可以点击查看一些同步的 小例子
参考阅读: