互斥与并发(3)—管程

1.管程(Monitor)

        用信号量设计一个正确的程序是很困难的,难点是semWaitsemSignal操作可能分布在整个程序中,但是很难看出这些在信号量上的操作所产生的整体效果。但是管程确易于设计。

       管程是由一个或多个过程、一个初始化序列和局部数据组成的软件模块,其主要特点如下:

1)  局部数据变量只能被管程的过程访问,任何外部过程都不能访问(封装,因为管程就是一个对象)。

2)  一个进程通过调用管程的一个过程进入管程。

3)  任何时候,只能有一个进程在管程中执行,调用管程的任何其他进程都被阻塞,以等待管程可用(通过这一点就实现了互斥,管程天生实现互斥)

        管程通过使用条件变量提供对同步的支持,这些条件变量包含在管程中,并且只有在管程中才能被访问。有两个函数可以操作条件变量:

       (在信号量的运用中,互斥是由信号量来实现的,各种条件也是有信号量来实现,所以信号量比较复杂,设计难度大,管程这两者分开考虑。)

       cwait(c):调用进程的执行在条件c上挂起,管程现在可以被另一个进程使用。

       csignal(c):恢复执行在cwait之后因为某些条件而挂起的进程。如果有多个这样的进程选择其中一个;如果没有这样的进程,什么也不做。

       注意管程的wait和signal操作与信号量不同。如果在管程中的一个进程发信号,但没有这个条件变量上等待的任务,则丢弃这个信号。

2.管程结构

3.管程例子代码

        下面给出一段用管程解决生产者/消费者问题的代码:

/* program producerconsumer */
monitor boundedbuffer;                           
char buffer [N]; 					/*N个元素大小的缓冲区*/
int nextin, nextout; 				/*缓冲区指针*/
int count; 						/*缓冲区中可用元素个数*/
cond notfull, notempty;             /*条件变量*/
void append (char x)
{
if (count == N) cwait(notfull);       /*缓冲区满,禁止写入,防止溢出*/
buffer[nextin] = x;
nextin = (nextin + 1) % N;
count++;							/*多了一个数据*/
csignal (nonempty);				/*通知消费者,缓冲区不空,可能有消费者阻塞*/
}
void take (char x)
{
if (count == 0) cwait(notempty); 	/*缓冲区空,禁止取数据,防止溢出*/
x = buffer[nextout];
nextout = (nextout + 1) % N);
count--;							 /*数据项少了一项*/
csignal (notfull); 					 /*通知生产者,缓冲区不满,可能有生产者阻塞*/
}
{                                /*管程体*/
nextin = 0; nextout = 0; count = 0; 	 /*缓冲区初始化为空*/
}
void producer()
{
char x;
while (true) {
produce(x);
append(x);
}
}
void consumer()
{
char x;
while (true) {
take(x);
consume(x);
}
}
void main()
{
parbegin (producer, consumer);
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值