版权声明:版权归游吟焰火所有,未经允许不得转载。 https://blog.csdn.net/chenzhanqi/article/details/82854991
问题描述:
有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者间设置了一个具有n个缓冲区的缓冲区池,生产者进程将其生产的产品放入一个缓冲区中,消费者进程可从一个缓冲区中取走产品去消费。尽管所有的生产者进程都是以异步方式运行的,但它们之间必须保持同步,既不允许消费者进程到一个空缓冲去取产品,也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区投放产品。
解决方法:
假定在生产者和消费者之间的公用缓冲池中具有n个缓冲区,消费者不能同时取一个缓冲区的产品,生产者不能同时向同一个缓冲区放入产品。生产者和消费者相互等效。
buffer[]:缓冲池,本例中组织成循环缓冲,即循环队列。
n:缓冲池的数量。
in、out:已存产品的单元指针和空闲单元的指针。(注:buffer[]为循环队列,存入时in=(in+1)%n,取出时out=(out+1)%n。)
互斥信号量mutex:实现诸进程对缓冲池的互斥利用。
信号量empty和full:缓冲池中空缓冲和满缓冲区的数量。
生产者producer类
int in=0,out=0;
item buffer[n];
semaphore mutex=1,empty=n,full=0;//定义信号量,mutex初始化为1可实现互斥
void producer(){
do{
producer an item nextp;
...
wait(empty); //将空缓冲信号量-1
wait(mutex); //实现缓冲区互斥使用
buffer[in]=nextp; //放入产品
in=(in+1)%n; //in+1
signal(mutex); //释放缓冲区资源
signal(full); //将满缓冲信号量+1
}while(TRUE);
}
消费者consumer类
//变量声明省略
void consumer(){
do{
wait(full); //将满缓冲信号量-1
wait(mutex); //实现缓冲区互斥使用
nextc=buffer[out]; //取走产品
out=(out+1)%n; //out-1
signal(mutex); //释放缓冲区资源
signal(empty); //将空缓冲信号量+1
consumer the item in nextc;
...
}while(TRUE);
}
主类
void main(){
cobegin
producer();
consumer();
coend
}
注意事项:
1、每个进程中用于实现互斥mutex的P、V操作必须成对出现。
2、empty和full的P、V操作也需要成对出现,但处于不同的进程中。
3、必须先执行资源信号量(empty和full)的P操作,再执行对互斥信号量(mutex)的P操作,否则可能引起进程死锁。
利用AND信号量解决生产者-消费者问题
生产者producer类
int in=0,out=0;
item buffer[n];
semaphore mutex=1,empty=n,full=0;
void producer(){
do{
producer an item nextp;
...
Swait(empty,mutex); //同时对两个信号量进行操作
buffer[in]=nextp;
in=(in+1)%n;
Ssignl(mutex,full); //释放资源
}while{TRUE};
}
消费者consumer类
void consumer(){
do{
Swait(full,mutex); //同时对两个信号量进行操作
nextc=buffer[out];
out=(out+1)%n;
Ssignal(mutex,empty); //释放资源
consumer the item in nextc;
}
}
主类省略