生产者-消费者问题
Posted 杀手不太冷!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生产者-消费者问题相关的知识,希望对你有一定的参考价值。
生产者-消费者问题
问题分析
系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。(注:这里的“产品”理解为某种数据)
生产者、消费者共享一个初始为空,大小为n的缓冲区。
只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。
只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。
缓冲区是临界资源,各进程必须互斥地访问。
如何实现:
semaphore mutex=1; //互斥信号量,实现对缓冲区的互斥访问
semaphore empty=n; //同步信号量,表示空闲缓冲区的数量
semaphore full=0; //同步信号量,表示产品的数量,也即非空缓冲区的数量
/*
把产品放入缓冲区和把产品从缓冲区取出来的时候都是需要互斥的,因为如果不互斥的话,可能会两个进程同时把一个产品放入缓冲区,这样后面的产品可能会把前面的产品覆盖,而实现互斥操作的方法是在把产品放入缓冲区和从缓冲区取产品操作的前后都加一个PV操作即P(mutex)和V(mutex),
把产品放入缓冲区操作和把产品从缓冲区里面取出来操作它们是双向同步,什么意思呢?就是把产品放入缓冲区之后紧接着要执行把产品从缓冲区里面取出来操作,而把产品从缓冲区里面取出来之后,紧接着也要执行把产品放入缓冲区里面的操作。怎么实现呢?请看下文:
先来看一下前操作:把产品放入缓冲区,后操作:从缓冲区取出一个产品的这种情况,这样把产品放入缓冲区之后会执行一个V操作,而V操作代表会多出一个资源,因此思考:把产品放入缓冲区之后哪个资源会多,当然是full(非空缓冲区的数量),所以在把产品放入缓冲区之后的V操作是V(full)操作,然后后操作,从缓冲区里取出一个产品之前会执行P操作,而P操作就代表着资源的减少,所以思考一下从缓冲区里取出一个产品之前什么资源会减少,当然是full(非空缓冲区的数量),因此后操作的前面执行的是P(full)
再来看一下前操作:从缓冲区取出一个产品,后操作:把产品放入缓冲区 的这种情况,从缓冲区取出一个产品之后会执行V操作,V操作代表资源增加,所以思考从缓冲区取出一个产品之后什么资源会增加?当然是empty(空缓冲区的数量),所以从缓冲区取出一个产品的后面要执行V(empty); 把产品放入缓冲区的前面会执行P操作,P操作代表着资源的减少,思考把产品放入缓冲区之后什么资源会减少?当然是empty(空缓冲区的数量),因此把产品放入缓冲区操作的前面应该执行P(empty);
最后要注意一个问题,就是同步相关的P操作一定要放在互斥相关的P操作的前面,否则会发生死锁问题,即生产者进程中的P(empty)要放在P(mutex)的前面,消费者中的P(full)也要放在P(mutex)的前面。
*/
producer(){
while(1){
生产一个产品;
P(empty);//消耗一个空闲缓冲区
P(mutex);//实现互斥是在同一进程中进行一对PV操作
把产品放入缓冲区;
V(mutex);//实现互斥是在同一进程中进行一对PV操作
V(full);//增加一个产品
}
}
consumer(){
while(1){
P(full);//消耗一个产品(非空缓冲区)
P(mutex);
从缓冲区取出一个产品;
V(mutex);
V(empty);//增加一个空闲缓冲区
使用产品;
}
}
不能改变相邻P、V操作的顺序
但如果实现互斥的P操作即P(mutex)放在实现同步的P操作的后面,也即是先P(empty),然后再P(mutex),这个时候假设缓冲区内已经放满产品,则empty=0,full=n,则执行P(empty)的时候,由于没有资源了,因此进程会发生阻塞,这样后面的P(mutex)就不会执行了,因此mutex的值仍然是1,这样的话,在消费者进程中执行P(mutex)的时候就不会发生阻塞了,因此就不会出现死锁问题了。
知识回顾与重要考点
生产者后消费者互为同步关系,即生产者生产操作执行之后要执行消费者消费操作,而消费者消费操作执行之后也要执行生产者生产操作,所以会有两个同步关系,所以同步的实现需要两个PV对,至于PV的参数是谁,你需要分析生产或消费操作之后什么资源时增加的,什么资源的减少的。
以上是关于生产者-消费者问题的主要内容,如果未能解决你的问题,请参考以下文章
请问如何用C语言实现“生产者与消费者问题”?(最好附上完整的C语言源代码)