管程, monitor

管程, monitor 管程, 监视器, Moniter Java程序设计语言中,每个对象都可以作为一个管程。需要互斥使用的方法必须明确标示关键字 synchronized . 代码块也可以标示关键字synchronized. 不使用明确的条件变量, Java的这种管程在入口队列之外,使用单独的条件等待队列. 所有等待的线程进入这个队列, 所有的notify与notify all操作也施加于这个队列。这种方法已经被其它程序设计语言使用,如C#. Java中的同步方法与其他经典管程有本质差别: Java没有内嵌的条件变量。反之,Java提供了两个过程wait和notify ,分别与sleep和wakeup等价, 不过,当它们在同步方法中使用时,它们不受竞争条件约束。理论上,方法wait可以被中断,它本身就是与中断有关的代码。Java需要显式表示异常处理。 在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) 这些方法只能在同步代码块或同步方法中调用。因为所有的这些方法都需要线程持有对象的锁,所以只能通过同步来实现。 管程 (英语: Moniters,也称为监视器) 是一种程序结构,结构内的多个子程序 (对象或模块) 形成的多个工作线程互斥访问共享资源。 这些共享资源一般是硬件设备或一群变量。管程实现了在一个时间点,最多只有一个线程在执行管程的某个子程序。 与那些通过修改数据结构实现互斥访问的并发程序设计相比,管程实现很大程度上简化了程序设计。 管程提供了一种机制,线程可以临时放弃互斥访问,等待某些条件得到满足后,重新获得执行权恢复它的互斥访问。 一个管程包含: 多个彼此可以交互并共用资源的线程 多个与资源使用有关的变量 一个互斥锁 一个用来避免竞态条件的不变量 一个管程的程序在运行一个线程前会先取得互斥锁,直到完成线程或是线程等待某个条件被满足才会放弃互斥锁。 若每个执行中的线程在放弃互斥锁之前都能保证不变量成立,则所有线程皆不会导致竞态条件成立。 当一个线程执行管程中的一个子程序时,称为占用(occupy)该管程. 管程的实现确保了在一个时间点,最多只有一个线程占用了该管程。这是管程的互斥锁访问性质。 当线程要调用一个定义在管程中的子程序时,必须等到已经没有其它线程在执行管程中的某个子程序。 在管程的简单实现中,编译器为每个管程对象自动加入一把私有的互斥锁。该互斥锁初始状态为解锁, 在管程的每个公共子程序的入口给该互斥锁加锁,在管程的每个公共子程序的出口给该互斥锁解锁。 条件变量(Condition Variable) 管程提供了一种实现互斥的简便途径,但这还不够。我们还需要一种办法使得线程在无法继续运行时被阻塞。 在生产者-消费者问题中,很容易将针对缓冲区满和缓冲区空的测试放到管程过程中,但是生产者在发现缓冲区满的时候如何阻塞呢? 解决的方法是引入条件变量 (condition variables) 以及相关的两个操作: wait和signal。 ...

2012-11-15 · 2 min · 274 words · -