一、问题描述
有一组生产者进程在生产产品,并将这些产品提供给一组消费者进程去消费。为使生产者进程与消费者进程能够并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区中;消费者可以从一个缓冲区中取走产品并消费。尽管所有的生产者进程和消费者进程都是以异步方式运行的,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区中去取产品;也不允许生产者进程向一个已装满产品且产品未被取走的缓冲区投放产品。
二、问题解析
该问题中,有一个互斥关系,两个同步关系。我们用互斥信号量mutex实现缓冲池的互斥共享;用信号量empty表示空缓冲池数量,实现生产者先放、消费者再取;用full表示满缓冲池数量,实现缓冲池满后,只允许消费者取产品。
初始状态下,mutex=1,empty=n,full=0。
先用mutex解决互斥共享关系:
void producer(){
do{
……
P操作
……
将产品放入指定缓冲区
……
V操作
}
}while(TRUE);
通过P操作将缓冲池锁上,等生产者放完产品后,消费者再去取:
void consumer(){
do{
……
P操作
……
从缓冲区取出产品
……
V操作
}
}while(TRUE);
这里的do while循环是为了防止信号量的值变为负数,从而避免了死锁的可能性。
实现缓冲池的互斥共享后,仍然存在问题,即生产者是不能往满缓冲区中投放产品的,只有等消费者取走产品之后,才能再次投放,所以还需要有一次对empty和full的PV操作:
void producer(){
do{
……
P操作
P操作
……
将产品放入指定缓冲区
……
V操作
V操作
}
}while(TRUE);
同理,消费者必须等待生产者投放产品之后才能取走产品:
void consumer(){
do{
……
P操作
P操作
……
从缓冲区取出产品
……
V操作
V操作
}
}while(TRUE);
在进行PV操作时,二者要成对出现,并且有多对操作时,应先执行同步,再执行互斥,否则可能产生死锁问题。
三、问题解答
int in=0,out=0;
item buffer[n];
semaphore mutex=1,empty=n,full=0;
void producer(){
do{
……
wait(empty);
wait(mutex);
buffer[in]=nextp;
in=(in+1)%n;
signal(mutex);
signal(full);
}
}while(TRUE);
void consumer(){
do{
……
wait(full)
wait(mutex)
nextc=buffer[out];
out=(out+1)%n;
signal(mutex);
signal(empty);
}
}while(TRUE);
void main(){
……
}