生产者消费者模式(转)

1.PV操作

PV操作是由P操作原语和V操作原语组成,对信号量进行操作。

P(S):意为占用,将信号量的值减1,S=S-1,如果S>=0,则该进程继续执行,否则进入等待队列;

V(S):意为释放,将信号量的值加1,S=S+1,如果S>0,则该进程继续执行,否则释放队列中第一个等待信号量的进程。

为了更形象的理解PV操作,可以联想一下电话亭场景:

P:第一个人占用电话亭打电话,可用电话亭数-1,S=S-1,接下来的人先检测S-1,如果S>=0,说明当前使用者有电话亭可用,如果S<0,说明无电话亭可用,S=-i说明自己刚好是第i个排队的人。

V:使用完电话亭就推门走开,将S加1,如果S>=2,说明这个人刚刚打电话时电话亭空闲一个;如果S=1,说明这个人刚好腾出一个空;如果S<=0说明有人排队,按照排队次序依次填补打电话。

2.同步和互斥

同步是进程之间直接的制约关系,体现工作次序,这种制约源于进程之间的合作,生产者和消费者关系就是同步关系。

互斥是进程之间间接的制约关系,这种制约源于对临界资源的访问,线程之间共享内存需要用到互斥关系。

生产者和消费者问题既是同步也是互斥的关系,一方面,作为平等进程,对缓冲区的访问时竞争关系,即互斥;另一方面,作为生产者和消费者两个进程有先后次序,存在合作关系所以是同步的。

3.生产者、消费者、缓冲区问题

①一个生产者,一个消费者,一个公共缓冲区: 只需保证,生产者先生产,消费者后消费,两者互斥使用缓冲区即可。m=1,n=0

生产者

{

生产产品

P(m)//保证生产者无法再生产

产品送往buffer

V(n)//唤醒消费者

}

消费者

{

P(n)//保证消费者不能先于生产者

从buffer取走产品

V(m)//唤醒生产者继续生产

消费产品

}

②一个生产者,一个消费者,无数个公共缓冲区:

与①不同在于,生产者可以不断生产,消费者可以不断消费,只需保证消费者有产品可消费。m=1,n=0

生产者

{

生产产品

P(m)

产品送往buffer

V(m)//可继续生产

V(n)//唤醒消费者

}

消费者

{

P(n)//保证有产品可消费,避免死锁

P(m)//阻止生产者生产

从buffer取走产品

V(m)//唤醒生产者生产

消费产品

}

注意点:P操作像是一个标志,进入临界区之前需要将互斥进程进行P操作,以免抢占资源

③一个生产者,一个消费者,n个环形缓冲区

与②类似,但②无限缓冲区即总有空闲区域可以生产,该情况需要检查缓冲区是否有空闲区域供生产,m=1,n=0,count=SIZEOFBUF

生产者

{

生产产品

P(count)//保证有空闲区域供生产,否则阻塞

P(m)

放入buffer

V(m)

V(n)//唤醒消费者

}

消费者

{

P(n)

P(m)

从buffer取产品

V(m)//唤醒生产者

V(count)//多空闲一个区域供生产者生产

消费产品

}

④两个生产者,两个消费者,一个公共缓冲区

两个生产者、两个消费者四者之间互斥使用公共缓冲区。增加两个互斥值,m=1.n=0

生产者

{

生产产品

P(m)//确定是生产者

放入buffer

V(n)//唤醒消费者

}

消费者

{

P(n)//保证有产品可消费

从buffer取产品

V(m)//唤醒生产者

}

⑤两个生产者,两个消费者,n环形缓冲区,count=SIZEOFBUF ,n=0,m =1,

生产者

{

生产产品

P(count)//保证有空闲区域供生产,否则阻塞

P(m)

放入buffer

V(m)

V(n)//唤醒消费者

}

消费者

{

P(n)

P(m)

从buffer取产品

V(m)//唤醒生产者

V(count)//多空闲一个区域供生产者生产

消费产品

}

原博客地址:http://www.cnblogs.com/aiheyiwen/p/4925810.html

自己的一点理解:其实P,V操作简单的可以理解为:我用了,给你用。当出现多个生产者,多个消费者的时候只需要在临界资源上互斥访问即可。

原文地址:https://www.cnblogs.com/handsomecui/p/6852032.html