问题基本描述
生产者消费者问题是一个著名的进程同步的问题。它描述的是:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费者进程可从一个缓冲区中取走产品消费。
一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区(实质在数据结构中是一个循环对列),只有缓冲区没满时,生产者才能把消息放入到缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源(必须进行互斥的访问),它只允许一个生产者放入消息,或者一个消费者从中取出消息。
生产者和消费者的共享变量:
int in = 0;out = 0;counter = 0;// 其中in相当于是输入指针,out相当于输出指针,counter是记录产品的数量
item buffer[n];// 缓冲区
注意:缓冲池组织为循环缓冲,输入指针加1表示为in=(in+1)mod n,输出指针加1表示为out=(out+1)mod n,当(in+1)mod n=out时表示缓冲池满,in=out表示缓冲池空。
问题解决
1) 关系分析:生产者和生产者之间是互斥访问缓冲区的,消费者和消费者之间是互斥访问缓冲区的。生产者和消费者之间是同步关系,相互依赖的关系。2)关系特点:
- 首先,生产者只需要关心“仓库”,并不需要关心具体的消费者。
- 对于消费者而言,它不需要关心具体的生产者,它只需要关心这个“仓库”中还有没有东西存在。
- 生产者生产的时候消费者不能进行“消费”,消费者消费的时候生产者不能生产,相当于一种互斥关系,即生产者和消费者一次只能有一人能访问到“仓库”。
- “仓库”为空时不能进行消费。
- “仓库”满时不能进行生产。
3) 信号量设置:信号量 mutex作为互斥信号量,它用于控制互斥访问缓冲池,互斥信号量初值为1;信号量full用于记录当前缓冲池中“满”缓冲区数,初值为0。信号量empty 用于记录当前缓冲池中“空”缓冲区数,初值为n。
semaphore mutex=1; //临界区互斥信号量
semaphore empty=n; //空闲缓冲区
semaphore full=0; //缓冲区初始化为空
void producer()
{ //生产者进程
while(1){
produce an item in nextp; //生产数据
wait(empty); //获取空缓冲区单元
wait(mutex); //进入临界区...
buffer[in] = nextp;
in = (in+1)%n
signal(mutex); //离开临界区,释放互斥信号量
signal(full); //满缓冲区数加1
}
}
void consumer ()
{ //消费者进程
while(1){
wait(full); //获取满缓冲区单元
wait(mutex); // 进入临界区
netxc = buffer[out];
out = (out+1)%n;
signal (mutex); //离开临界区,释放互斥信号量
signal (empty) ; //空缓冲区数加1
consume the item; //消费数据
}
}
void main()
{
cobegin
prodncer();
consumer();
coend;
}