内容正文:
操作系统原理(第2版)
为了解决信号量机制带来的不便而引入了管程同步机制。
管程(Monitor)是一种新的进程互斥与同步机制,它能够提供与信号量同等的功能。使用管程机制可以将分散在各进程中的同步操作集中起来统一控制和管理,更方便地实现进程的互斥与同步,同时也可以减少错误的发生。
3.6 管程机制
3.6.1 条件变量与管程结构
1. 条件变量
为了避免多个进程在管程中出现“忙等”现象,管程提供了条件变量机制,让暂时不能进入管程的进程阻塞或挂起等待。条件变量(Condition Variable)是管程提供的一种进程同步机制,它能够在多个进程之间传递信号并解决管程内进程可能出现的“忙等”问题。
条件变量是封装在管程内的一种数据结构,它对应一个进程阻塞队列并只能被管程中的过程(函数)访问,且是管程内的所有过程(函数)的全局变量。条件变量只能通过wait和signal两个原语进行控制,而wait和signal原语总是在某个条件变量(如X)上执行,表示为X.wait或X.signal。X.wait操作的作用是使本进程阻塞在条件变量X上,X.signal操作的作用是:若有进程的被阻塞在条件变量X上,则将第一个阻塞进程唤醒。
3.6 管程机制
条件变量与信号量的区别:
(1)与信号量具有值的概念不同,条件变量没有关联的值;
(2)在管程中执行signal操作时,如果相应的阻塞队列中没有阻塞进程则本次操作为空操作,即什么也不做;
(3)在信号量中则不会出现这种情况,V操作在阻塞队列中没有阻塞进程时也必须对信号量进行加1操作(资源个数增1)。
3.6 管程机制
2. 管程结构
管程的性质:
(1)管程中不仅有数据而且有对数据的操作,即管程是一种扩展了的抽象数据类型。
(2)管程这种扩展了的抽象数据类型的描述对象是互斥资源,因此,管程实际上是互斥资源的管理模块。
(3)作为一个软件模块,管程应符合模块化的要求,即管程应是一个基本程序单位,并可以被单独编译。
(4)管程中的数据结构只能被管程中的过程(函数)使用,管程内的数据结构和过程(函数)的具体实现在外部是不可见的。
(5)为了实现对互斥资源的共享,管程应有互斥与同步机制。
3.6 管程机制
管程的定义:一个管程定义了一个数据结构和在该数据结构上执行的一组过程(函数),这组过程(函数)能够同步进程和改变管程中的局部数据。
管程的组成:
(1)局部于管程内的数据结构;
(2)管程内共享数据的初始化语句;
(3)一组对管程内数据结构进行访问的调用过程(函数)。
3.6 管程机制
使用管程实现进程同步的特点:
(1)管程内的数据结构只能由管程定义的过程(函数)访问,任何外部过程(函数)都不能访问它们。
(2)任何时刻只能有一个进程在管程中执行,其他申请进入管程的进程必须阻塞等待。
(3)一个外部过程(函数)只有通过调用管程内的一个过程(函数)才能进入管程。
3.6 管程机制
管程描述如下:
monitor 管程名
{
公用变量说明;
条件变量说明;
初始化语句;
define 管程内定义的,管程外可以调用的过程或函数名列表;
use 管程外定义的,管程内将要调用的过程或函数名列表;
过程或函数1定义;
过程或函数2定义;
…
过程或函数k定义;
}
3.6 管程机制
例题:在公共汽车上,司机和售票员各司其职地工作(各自相当于一个独立运行的进程)。司机只有等售票员关好车门后才能启动汽车,售票员只有等司机停好车后才能开车门,两者必须密切配合、协调一致。
管程在进程同步中的应用
司机和售票员管程实现程序
monitor Drive_bus
{
int flag=0;
condition notrun,notstart;
define drive,ticketing;
void drive() //开车函数
{
while(1)
{
if(flag<>1)
notrun.wait;
启动汽车;
正常行驶;
到站停车;
flag=2;
notstart.signal;
}
}
void ticketing() //售票函数
{
while(1)