生产者与消费者问题
-
PV操作是用来操作信号量的。
-
P:等待——wait——减法作用——阻塞作用
-
V:释放——signal——加法作用——唤醒作用
-
S.value > 0:有空闲CPU;S.value = 0:CPU刚好用完;S.value < 0:进程等待;-
P操作
void wait(S) { S.value--; if (S.value < 0) { 加入阻塞队列; } }-
V操作
void signal(S) { S.value++; if (S.value <= 0) { 唤醒阻塞队列第一个进程; } } -
-
-
解题思路:
1.画图理解题目 2.判断题目类型 3.分析进程数目,填写进程模板 4.补充基本代码 5.补充P,V代码 6.调整代码
-
例:爸爸往桌子上每次放一个苹果,儿子每次从桌子上拿一个苹果,放苹果和拿苹果不能同时进行,桌子上最多放10个苹果,用PV操作实现同步互斥。
-
分析:爸爸——生产者——剩余空间(empty) = 10
儿子——消费者——已占用空间(full) = 0
信号量S = 1,用来实现互斥。
-
特征:①容器 ≤ 容量
②生产 消费
-
伪代码
Dad() { while(1) { P(empty);//判断盘子是否已满 P(S); 放苹果; V(S); V(full);//对已占用空间+1 } }Son() { while() { P(full);//判断盘子是否为空 P(S); 取苹果; V(S); V(empty);//对盘子剩余空间+1 } } -
-
例:桌子上有个盘子,每次只能放一个水果,妈妈放橘子,爸爸放苹果,儿子吃橘子,女儿吃苹果。盘子为空,爸爸或妈妈才能放水果,盘子有水果时,儿子和女儿才能取水果。
-
分析:
-
初始值:
orange= 0
apple= 0
plate= 1
S= 1 -
伪代码
Mom() { while(1) { P(plate); P(S); 放橘子; V(S); V(orange); } }Dad() { while(1) { P(plate); P(S); 放苹果; V(S); V(apple); } }Son() { while(1) { P(orange); P(S); 取橘子; V(S); V(plate); } }Daughter() { while(1) { P(apple); P(S); 取苹果; V(S); V(plate); } }-
操作同一个对象的时候,使用信号量S来实现互斥。
-
-
-
[2015—408统考]
-
有A,B两个人通过信箱辩论,每个人都从自己的信箱取得对方的问题,将答案和新问题组成一个邮件放入对方的信箱中。假设A的信箱可装M封邮件,B的信箱可装N封邮件。初始时A信箱有X封,B信箱有Y封,,辩论者每次只取一封邮件。请用P,V操作实现,并解释信号量的初始值和含义。
-
分析:生产者A——B的剩余空间
生产者B——A的剩余空间
消费者A——自己邮箱还有多少封信
消费者B——自己邮箱还有多少封信
full-A:A信箱有多少封邮件
empty-A:A信箱的容量
full-B:B信箱有多少封邮件
empty-B:B信箱的容量
mutex-A:A信箱的信号量
mutex-B:B信箱的信号量 -
初始值:
mutex-A= 1,mutex-B= 1
full-A= x ,empty-A= M - X
full-B= y,empty-B= N - y
A() { while(1) P(full-A); P(mutex-A); 从自己邮箱取信; V(mutex-A); V(empty-A); 读信; P(empty-B); P(mutex-B); 向B邮箱投信; V(mutex-B); V(full-B); }B() { while(1) P(full-B); P(mutex-B); 从自己邮箱取信; V(mutex-B); V(empty-B); 读信; P(empty-A); P(mutex-A); 向A邮箱投信; V(mutex-A); V(full-A); } -
-
-
[2014—408统考]
-
例:系统中有多个生产者和消费者,共享一个能存放1000件产品的环形缓冲区(初始为空)。当缓冲区未满时生产者可放入生产的一个产品,否则等待。当缓冲区未空时,消费者进程可取走一件产品,否则等待。要求一个消费者从缓冲区连续取10件产品后,其他消费者才能取走产品。请用P,V操作实现该流程并解释信号量含义。
-
分析:
生产者(j)—剩余空间
生产者(i)—剩余空间
消费者(m)—物件数量
消费者(n)—物件数量 -
初始值:
empty= 1000;
full= 0;
mutex= 1;
mutex1= 1;
j() { while(1) { P(empty); P(mutex); 放一件产品; V(mutex); V(full); } }i() { while(1) { P(empty); P(mutex); 放一件产品; V(mutex); V(full); } }m() { while(1) { P(mutex1); for(int i = 0;i < 10;i++) { P(full); P(mutex); 取一件物品; V(mutex); V(empty); } V(mutex1); } }n() { while() { P(mutex1); for(int i = 0;i < 10;i++) { P(full); P(mutex); 取一件物品; V(mutex); V(empty); } V(mutex1); } }-
上述代码中,
m和n,i和j的代码一样,所以合并m和n,i和j。
-
-