作用
管程保证了同一时间只能有一个进程在管程内活动,使用condition变量让进入管程而无法继续执行的进程阻塞自己。
例子
先来看一段有问题的代码:
#define TRUE 1
#define MAX 100
void insert_item(int);
int remove_item();
int count = 0;
void producer()
{
int item;
while(TRUE)
{
item = produce_item();
if( count == MAX ) sleep();
insert_item(item);
count += 1;
if( count == 1) wakeup(consumer); /*buffer由空变非空后唤醒挂起的消费者*/
}
}
void consumer()
{
int item;
while(TRUE)
{
if( count == 0 ) sleep();
item = remove_item();
count -= 1;
/*buffer由满变不满后唤醒生产者*/
if( count == MAX - 1 ) wakeup(producer);
consume_item(item);
}
如果producer在consumer sleep之前发送wakeup信号则会导致错误:比如消费者在item为空的时候检测到count==0,但是这时候被切换走了,去了生产者。生产者发送wakeup,但是丢失了。
/* 定义管程 PC */
monitor PC
{
int count = 0;
/* 我们使用条件变量full 表示被填满的buffer, empty 表示空的buffer */
conditon full, empty;
void insert(int item)
{
/* 当buffer满的时候,我们在full上将插入操作阻塞 */
if ( count == MAX ) wait(&full);
insert_item(item);
count += 1;
/* 当buffer不空的时候,我们在empty上唤醒取出操作 */
if ( count == MAX -1 ) signal(&empty);
}
int remove()
{
/* 当buffer空的时候,我们在empty上将取出操作阻塞 */
if( count == 0 ) wait(&empty);
remove_item(item);
count -= 1;
/* 当buffer不满的时候,我们在full上唤醒插入操作 */
return item;
if( count == MAX - 1) signal(&full);
}
}
void producer()
{
int item;
item = produce_item();
/*调用管程中的函数 */
PC.insert(item);
}
void consumer()
{
int item;
/*调用管程中的函数 */
item = PC.remove();
consumer_item();
}
注意 以上代码 用类似于C的代码写成 ,但 C语言并不支持管程。
这样,在insert或者remove的时候就不会被切换走了。