经典进程同步与互斥问题——生产者消费者问题

问题描述:生产者——消费者问题是指有两组进程共享一个环形的缓冲池,一组称为生产者,一组称为消费者。缓冲池是由若干个大小相等的缓冲区组成,每个缓冲区可以容纳一个产品。生产者进程不断的将产品放入缓冲池中,消费者不断将产品从缓冲池中取出。

核心:生产者——消费者问题,既存在着进程同步问题,也存在着临界区互斥问题。当缓冲区满时,表示供大于求,生产者必须停止生产,进入等待状态,同时唤醒消费者;当所有缓冲区都为空时,表示供不应求,消费者必须停止消费,唤醒生产者。这就是生产者进程和消费者进程的同步关系。对于缓冲池,生产者和消费者都要使用它,显然他是一个临界资源,对于缓冲池的操作必须是互斥的。

这里采用P、V操作解决生产者消费者问题的形式化描述

semaphore mutex=1;
semaohore empty=n;
semaphore full=0   //定义是3个信号量
int i,j;
ITEM buffer[n];
ITEM data_p,data_c;
void producer()
{
while(true)
{
produce an item in data_p;
P(empty);
P(mutex);
buffer[i]=data_p;
i=(i+1)%n;
V(mutex);
V(full);
}
}

void consumer()
{
while(true)
{
P(full);
P(mutex);
data_c=buffer[j];
j=(j+1)%n;
V(mutex);
V(empty);
consume the item in data_c;
}
}

总结:

1.把共享缓冲池的n个缓冲区视为临界资源,进程在使用时,首先要检查是否有其他进程在临界区,确认没有时在进入。在程序中,P(mutex)和V(mutex)用于实现对临界区的互斥,P(mutex)和V(mutex)必须成对出现。

2.信号量full表示有数据的缓冲区的数目,初始值为0,empty表示空闲缓冲区的数目,初始值为n。他们表示的都是资源的数目,因此称为资源信号量。实际上,full和empty之间存在关系,full+empty=n。对资源信号量的PV操作同样需要成对出现,与互斥信号量不同的是,P操作和V操作分别处于不同的程序中,例如P(empty)在生产者进程中,而V(empty)在消费者进程中。当生产者进程因执行P(empty)而阻塞时,由消费者进程的V(empty)将其唤醒;同理,当消费者进程因执行P(full)而阻塞时,生产者进程用V(full)将其唤醒。

思考:在生产者进行中的P(empty)和P(mutex)的位置能否互换?

显然是不能的,如果交换后,就可能会发生死锁。可以想象这种情况,生产者进程,执行P(mutex)进入临界区,接下来执行P(empty),但现在empty为0,生产者被阻塞无法继续生产,用时它又已经进入了临界区,消费者进行由于无法进入临界区,也被阻塞。这样整个系统都被阻塞,发生死锁现象。


你可能感兴趣的:(经典进程同步与互斥问题——生产者消费者问题)