江小南
2023/04/22阅读:32主题:萌绿
【操作系统】生产者、消费者问题模型
1. 生产者、消费者问题
1. 问题描述
系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。(注:这里的“产品”理解为某种数据)。
生产者、消费者共享一个初始为空、大小为n的缓冲区。
只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。
只有缓冲区不空时,消费者才能从中取走产品,否则必须等待。
缓冲区是临界资源,各进程必须互斥地访问。
2. 问题分析
将生产者、消费者问题抽象为进程同步问题。
PV操作分析步骤:
-
关系分析。找出描述中的各个进程,分析它们之间的同步、互斥关系。 -
整理思路。根据各进程的操作流程确定P、V操作的大致顺序。 -
设置信号量。根据条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初值要看对应资源的初始值是多少)

3. 如何实现
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操作顺序可以交换。
2. 多生产者、多消费者问题
1. 问题描述
桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿才可以从盘子中取出水果,用PV操作实现上述过程。

2. 问题分析
PV操作分析步骤:
-
关系分析。找出描述中的各个进程,分析它们之间的同步、互斥关系。 -
整理思路。根据各进程的操作流程确定P、V操作的大致顺序。 -
设置信号量。根据条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初值要看对应资源的初始值是多少)
互斥关系:(mutex=1)
对缓冲区(盘子)的访问要互斥地进行。
同步关系(一前一后):
-
父亲将苹果放入盘子后,女儿才能取走苹果。 -
母亲将橘子放入盘子后,儿子才能取走橘子。 -
只有盘子为空时,父亲或母亲才能放入水果。
“盘子为空”这个事件可以由儿子或女儿触发,事件发生后才允许父亲或母亲放水果。

3. 如何实现
semaphore mutex=1; // 实现互斥访问盘子(缓冲区)
semaphore apple=0; // 盘子中有几个苹果
semaphore orange=0; // 盘子中有几个橘子
semaphore plate=1; // 盘子中还可以放多少个水果
// 生产者1 父亲
dad(){
while(1){
准备一个苹果;
P(plate);
P(mutex);
把苹果放入盘子;
V(mutex);
V(apple);
}
}
// 生产者2 母亲
mom(){
while(1){
准备一个橘子;
P(plate);
P(mutex);
把橘子放入盘子;
V(mutex);
V(orange);
}
}
// 消费者1 女儿
daughter(){
while(1){
P(apple);
P(mutex);
从盘子中取出苹果;
V(mutex);
V(plate);
吃掉苹果;
}
}
// 消费者2 儿子
son(){
while(1){
P(orange);
P(mutex);
从盘子中取出橘子;
V(mutex);
V(plate);
吃掉橘子;
}
}
说明:这里缓冲区大小为1,那么可以不用设置互斥信号量mutex也可以实现上述逻辑。而如果缓冲区大小大于1,就必须设置互斥信号量mutex来保证互斥访问缓冲区,负责会出现多个生产者同时访问缓冲区同一个区域的,导致前一个生产者生产的数据被后一个生产者生产的数据所覆盖的问题。
3. 小结
1. P V操作顺序问题
注意:实现互斥的P操作一定要在实现同步的P操作之后,否则容易造成死锁的问题。
2. P V操作分析步骤
PV操作分析步骤:
-
关系分析。找出描述中的各个进程,分析它们之间的同步、互斥关系。 -
整理思路。根据各进程的操作流程确定P、V操作的大致顺序。 -
设置信号量。根据条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初值要看对应资源的初始值是多少)
3. 限号量机制应用
信号量机制可以实现互斥、同步、对一类资源的申请和释放。
互斥:设置初值为1的互斥信号量。
同步:设置初值为0的同步信号量。(实现“一前一后”)
对一类资源的申请和释放:设置一个信号量,初始值即为资源的数量(本质上也属于“同步问题”,若无空闲资源,则申请资源的进程需要等待别的进程释放资源才能继续往下执行)
4. 生产者和消费者问题
生产者每次要消耗(P)一个空闲缓冲区,并生产(V)一个产品。
消费者每次要消耗(P)一个产品,并释放(V)一个空闲缓冲区。
往缓冲区放入/取走产品需要互斥。
作者介绍