管程

管程是一种高级的同步原语。
重要特性:任意时刻管程中只能有一个活跃进程。
它是一种编程语言的组件,所以编译器知道它们很特殊,并可以采用与其他过程调用不同的方法来处理它们。典型地,当一个进程调用管程中的过程,前几条指令将检查在管程中是否有其他的活跃进程。如果有,调用进程将挂起,直到另一个进程离开管程。如果没有,则调用进程便进入管程。
对管程的实现互斥由编译器负责!
在Java中,只要将关键字synchronized加入到方法声明中,Java保证一旦某个线程执行该方法,就不允许其他线程执行该方法,就不允许其他线程执行该类中的任何其他方法。
 
注意:管程是一个编程语言概念。编译器必须要识别出管程并用某种方式对互斥做出安排。C、Pascal及多数其他语言都没有管程,所以指望这些编译器来实现互斥规则是不可靠的。
 
下面的来自wikipedia:

管程 (英语Moniters,也称为监视器) 是一种程序结构,结构内的多个子程序(对象模块)形成的多个工作线程互斥访问共享资源。这些共享资源一般是硬件设备或一群变量。管程实现了在一个时间点,最多只有一个线程在执行管程的某个子程序。与那些通过修改数据结构实现互斥访问的并发程序设计相比,管程实现很大程度上简化了程序设计。

管程提供了一种机制,线程可以临时放弃互斥访问,等待某些条件得到满足后,重新获得执行权恢复它的互斥访问。

管程是东尼·霍尔 [1] 与泊·派克·汉森 [2]提出的,并由泊·派克·汉森首次在并行Pascal中实现。东尼·霍尔证明了这与信号量是等价的。管程在当时也被用于单操作系统环境中的进程间通信。

在编程语言Concurrent PascalPascal-PlusModula-2Modula-3Mesa以及Java中都提供这个功能。

一个管程包含:

一个管程的程序在运行一个线程前会先取得互斥锁,直到完成线程或是线程等待某个条件被满足才会放弃互斥锁。若每个执行中的线程在放弃互斥锁之前都能保证不变量成立,则所有线程皆不会导致竞态条件成立。

以下这个银行账户的提款/存款事务的管程是个简单的例子:

monitor class Account {
  private int balance := 0
  invariant balance >= 0

  public method boolean withdraw(int amount)
     precondition amount >= 0
  {
    if balance < amount then return false
    else { balance := balance - amount ; return true }
  }

  public method deposit(int amount)
     precondition amount >= 0
  {
    balance := balance + amount
  }
}

当一个线程执行管程中的一个子程序时,称为占用(occupy)该管程. 管程的实现确保了在一个时间点,最多只有一个线程占用了该管程。这是管程的互斥锁访问性质。

当线程要调用一个定义在管程中的子程序时,必须等到已经没有其它线程在执行管程中的某个子程序。

在管程的简单实现中,编译器为每个管程对象自动加入一把私有的互斥锁。该互斥锁初始状态为解锁,在管程的每个公共子程序的入口给该互斥锁加锁,在管程的每个公共子程序的出口给该互斥锁解锁。

这个例子中的不变量是“任何操作运行前 balance 变量必须反映正确的余额”。一般而言,不变量的条件不被写在程序中,而在注解中有相关说明,然而Eiffel程序设计语言检查不变量。


管程作为一个模块,它的类型定义如下:
    monitor_name = MoNITOR; 
       共享变量说明; 
       define 本管程内部定义、外部可调用的函数名表; 
       use 本管程外部定义、内部可调用的函数名表; 
       内部定义的函数说明和函数体 
       { 
         共享变量初始化语句; 
       } 
 
 
 
原文地址:https://www.cnblogs.com/youxin/p/3587038.html