生产者/消费者问题也叫缓存绑定问题(bounded- buffer),是一个经典的、多进程同步问题。
单生产者和单消费者
仓库容量为一的情况
问题分析:
- 仓库有空位时,生产者才能生产产品,并放入仓库中;
- 仓库中存在产品时,消费者才能将产品从仓库中拿出来消费。
解决方法:
这是一个典型的同步问题,定义两个信号量:
- 信号量S1:(代表仓库中空位的数量)保证生产者不向满仓库中放入产品;
- 信号量S2:(代表仓库中产品的数量)保证消费者不从空仓库中取出产品。
伪代码
S1=1
S2=0
//P进程(生产者进程)
while(true){
//生产一个产品
P(S1)
//把产品放入缓冲区
V(S2)
}
//Q进程(消费者进程)
while(true){
P(S2)
//从缓冲区中取出一个产品
V(S1)
//消费该产品
}
仓库容量为N的情况
问题分析:
- 仓库有空位时,生产者才能生产产品,并放入仓库中;
- 仓库中存在产品时,消费者才能将产品从仓库中拿出来消费。
解决方法:
这是一个典型的同步问题,定义两个信号量:
- 信号量S1:(代表仓库中空位的数量)保证生产者不向满仓库中放入产品;
- 信号量S2:(代表仓库中产品的数量)保证消费者不从空仓库中取出产品。
伪代码
S1=N
S2=0
//P进程(生产者进程)
i=0
while(true){
//生产一个产品
P(S1)
//把产品放入缓冲区Buffer[i]
V(S2)
i=(i+1)%N
}
//Q进程(消费者进程)
j=0
while(true){
P(S2)
//从缓冲区Buffer[j]中取出一个产品
V(S1)
//消费该产品
i=(i+1)%N
}
仓库容量为无穷大的情况
信号量S1:(代表仓库中空位的数量无穷大)在任何时候都有空位,因此不需要S1。
伪代码
S2=0
//P进程(生产者进程)
i=0
while(true){
//生产一个产品
//把产品放入缓冲区Buffer[i]
V(S2)
i=(i+1)
}
//Q进程(消费者进程)
j=0
while(true){
P(S2)
//从缓冲区Buffer[j]中取出一个产品
//消费该产品
j=(j+1)
}
多生产者和多消费者
设有N个缓冲区、M个生产者、K个消费者。
问题分析:
- 仓库有空位时,生产者才能生产产品,并放入仓库中;
- 仓库中存在产品时,消费者才能将产品从仓库中拿出来消费;
- 在同一时间,只能有一个生产者操作缓冲区,只能有一个消费者操作缓冲区。
生产者和消费者所操作的缓冲区数组的下标不一致,因此可以并行操作。
解决方法:
这是一个典型的同步问题,定义两个信号量:
- 信号量S1:(代表仓库中空位的数量)保证生产者不向满仓库中放入产品;
- 信号量S2:(代表仓库中产品的数量)保证消费者不从空仓库中取出产品;
- 互斥量M1:保证生产者串行地访问缓冲区;
- 互斥量M2:保证消费者串行地访问缓冲区。
伪代码
S1=N
S2=0
//P进程(生产者进程)
i=0
while(true){
//生产一个产品
P(S1)
P(M1)
//把产品放入缓冲区Buffer[i]
i=(i+1)%N
V(M1)
V(S2)
i=(i+1)
}
//Q进程(消费者进程)
j=0
while(true){
P(S2)
P(M1)
//从缓冲区Buffer[j]中取出一个产品
j=(j+1)%N
V(M1)
V(S1)
//消费该产品
}