文章目录
- 生产者、消费者问题描述
- PV操作题目分析步骤
- 多生产者、多消费者问题描述
- 问题分析
- 吸烟者问题描述
- 问题分析
生产者、消费者问题描述
系统中有一组生产者进程和一组消费者进程,生产者进程每次生成一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。(注:这里的“产品”理解为某种数据)
生产者、消费者共享一个初始为空、大小为n的缓冲区。
只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。
只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。
缓冲区是临界资源,各进程必须互斥地访问。
PV操作题目分析步骤
- 关系分析,找出题目中描述的各个进程,分析它们之间的同步互斥关系。
- 整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
- 生产者每次要消耗(P)一个空闲缓冲区,并生产(V)一个产品。
- 消费者每次消耗(P)一个产品,并释放一个空闲缓冲区(V)
- 往缓冲区放入/取走产品需要互斥。
- 设置信号量。设置需要的信号量,并根据题目条件确定信号量初值(互斥信号量初值一般为1,同步信号量的初值要看对应资源的初始值是多少)
semaphore mutex = 1; //互斥信号量,实现对缓冲区的互斥访问
semaphore empty = n; //同步信号量,表示空闲缓冲区的数量
semaphore full = 0; //同步信号量,表示产品的数量,也即非空缓冲区的数量
producer (){
while(1){
生产一个产品;
P(empty);
P(mutex);
把产品放入缓冲区;
V(mutex);
V(full);
}
}
consumer (){
while(1){
P(full);
P(mutex);
从缓冲区取出一个产品;
V(mutex);
V(empty);
使用产品
}
}
- 实现互斥的P操作一定要在实现同步的P操作之后,否则会导致“死锁”
- V操作不会导致进程阻塞,因此两个V操作顺序可以交换。
多生产者、多消费者问题描述
桌子上有一个盘子,每次只能向其中放入一个水果,爸爸专向盘子中放苹果,妈妈放橘子,儿子吃盘子中的橘子,女儿吃苹果。只有盘子空时,爸爸妈妈才能放一个水果,仅当盘子中有需要的水果时,儿子女儿才可以从盘子中取出水果。
用PV操作实现上述过程
问题分析
- 关系分析:
- 互斥关系:对缓冲区(盘子)的访问要互斥地进行
- 同步关系
- 父亲将苹果放入盘子后,女儿才能取苹果
- 母亲将橘子放入盘子后,儿子才能取橘子
- 只有盘子为空时,父亲或母亲才能放水果
- 整理思路,根据进程地操作流程确定P、V操作的大致顺序(互斥:在临界区前后分别PV。同步:前V后P)
- 设置信号量
semaphore mutex = 1; //实现互斥访问盘子(缓冲区)
semaphore apple = 0; //盘子中有几个苹果
semaphore orange = 0; //盘子中有几个橘子
semaphore plate = 1; //盘子中还可以放多少个水果
dad (){
while(1){
准备一个苹果;
P(plate);
P(mutex);
把苹果放入盘子;
V(mutex);
V(apple);
}
}
mom (){
while(1){
准备一个橘子;
P(plate);
P(mutex);
把橘子放入盘子;
V(mutex);
V(orange);
}
}
daughter (){
while(1){
P(apple);
P(mutex);
从盘中取出苹果;
吃掉苹果;
V(mutex);
V(plate);
}
}
son (){
while(1){
P(orange);
P(mutex);
从盘中取出橘子;
吃掉橘子;
V(mutex);
V(plate);
}
}
吸烟者问题描述
假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停的卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草,第二个有纸,第三个有胶水。供应者进程无线的提供三种材料,供应者每次将两种材料放桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者一个信号告诉完成了,供应者就会放另外两种材料在桌上,这个过程一直重复(让三个抽烟者轮流地抽烟)
问题分析
- 关系分析
- 桌子可以抽象为容量为一地缓冲区,要互斥访问
- 同步关系(组合一:纸、胶水;组合二:烟草、胶水;组合三:烟草、纸)
- 桌子上有组合一:第一个抽烟者取走
- 桌子上有组合二:第二个抽烟者取走
- 桌子上有组合三:第三个抽烟者取走
- 发出完成信号:供应者将下一个组合放到桌上
- 整理思路
- 设置信号量
semaphore offer1 = 0; //桌子上组合一地数量
semaphore offer2 = 0; //桌子上组合二地数量
semaphore offer3 = 0; //桌子上组合三地数量
semaphore finish = 0; //抽烟是否完成
int i = 0; //用于实现“三个抽烟者轮流抽烟”
provider (){
while(1){
if(i==0){
将组合一放到桌上;
V(offer1);
}else if(i==1){
将组合二放到桌上;
V(offer2);
}else if(i==2){
将组合三放到桌上;
V(offer3);
}
i = (i+1)%3;
P(finish)
}
}
smoker1 (){
while(1){
P(offer1);
从桌上拿走组合一;卷烟;抽掉;
V(finish);
}
}
smoker2 (){
while(1){
P(offer2);
从桌上拿走组合一;卷烟;抽掉;
V(finish);
}
}
smoker3 (){
while(1){
P(offer3);
从桌上拿走组合一;卷烟;抽掉;
V(finish);
}
}