管程 — Java同步的基本思想


如果你在大学里学习过操作系统课程,你可能会记得,管程(monitor)是操作系统中的一个重要概念。它也可用于Java同步中。这篇文章使用了一个比喻来解释“管程”的基本思想。

1.什么是管程

管程可以被认为是一个建筑物,其中包含一个特殊的房间(下图的special room)。该特殊的房间在同一时间只能由一个客户(线程)占用,通常包含一些数据和代码。

如果一个客户想要占据这个特殊房间,他必须先进入走廊(在上图是Hallway,在java中是Entry Set)等待。调度器将根据某些标准(例如FIFO先进先出)来选择一个客户。如果他出于某种原因中止,那么他将被送到等待室(上图wait room),并且在一段时间之后被安排重新进入特殊房间。正如上图所示,这座大楼里包含3间房间。

简单来说,管程是用来监视线程对这个特殊房间的访问。它确保只有一个线程能够访问受保护的数据或代码。

2.在JAVA中是如何实现管程?

在Java虚拟机中,每个对象和类在逻辑上与管程相关联。为了实现管程的互斥能力,一个锁(有时也称为一个互斥锁)关联每个对象和类。这就是所谓操作系统书籍上的信号量(semaphore),互斥锁是一个二进制信号量。

如果一个线程拥有一些数据的锁,那么没有其他线程可以获取这个锁,直到拥有锁的线程释放它。当我们做多线程编程时,如果任何时候都需要编写一个信号量,这将是不方便。幸运的是,我们并不需要,因为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)

这些方法只能在同步代码块或同步方法中调用。因为所有的这些方法都需要线程持有对象的锁,所以只能通过同步来实现。


原文链接:https://blog.csdn.net/qq_33873431/article/details/80348205