生产者-消费者问题(The Producer-Consumer Problem)是并发处理中最常见的一类同步抽象描述。先考虑但缓冲区的情况:有一个生产者进程P和一个消费者进程C公用一个缓冲区,P生产产品放入缓冲区,C从缓冲区取产品来消费。
同步问题:P进程不能往“满”的缓冲区中放入产品,C进程不能从“空”的缓冲区中取产品。
互斥问题:缓冲区不能同时被P和C使用。
解决方法:设置两个信号量full,empty,full表示缓冲区是否有产品,初值为0,empty表示缓冲区是否为空,初值为1.
1、解决单缓冲区生产者-消费者问题的描述如下:
struct semaphore
{
int value;
pointer_PCB quene;
}
semaphore S;
semaphore empty = 1;
semaphore full = 0;
main()
{
cobegin
producer();
consumer();
coend();
}
生产者-消费者进程描述如下:
void producer() void consumer()
{ {
while(true) while(true)
{ {
生产一个产品; P(fulll);
P(empty); 从缓冲区去产品;
送产品到缓冲区; V(empty);
V(full); 消费产品;
} }
} }
2、考虑多个缓冲区的情况:设有若干个生产者进程P1,P2,···,Pn,若干个消费者进程C1,C2,···,Cm,它们通过一个缓冲池(由k个缓冲区组成)联系起来,如图所示
设每个缓冲区存放一个“产品”,生产者进程不断的生产产品,并把它们放入到缓冲池中,消费者进程不断的从缓冲池中取出产品并消费。
同步问题:当缓冲池已经放满了产品时,生产者进程必须等待;当缓冲池已空时,消费者进程必须等待
互斥问题:互斥存在于所有进程之间,所有进程应互斥使用缓冲池这一临界资源
为了了解生产者-消费者问题,需设置若干信号量:full,empty,mutex.其中mutex是互斥信号量,用于对缓冲池这一临界资源的互斥访问;full,empty是同步信号量,分别表示缓冲池满和空的数量。
void main()
{
int full(0),empty(0),mutex(1);
int in = out = 0;
buffer[n];
cobegin
producer();
consumer();
coend
}
void producer()
{
while(true)
{
···
Producer an item in nextp;//生产一件产品
···
P(empty);
P(mutex);
buffer[in] = nextp;//向缓冲区存放一件产品
in = (in +1)%n;
V(mutex);
V(full);
}
}
void consumer()
{
while(true)
{
P(full);
P(mutex);
nextc = buffer[out];//从缓冲区取走一件产品
out = (out+1)%n;
V(mutex);
V(empty);
consumer the item nextc;//消费一件产品
}
}