1.对于问题的描述:
- 系统中有一组生产者进程和一组消费者进程
- 生产者和消费者共享一个初始为空、大小为n的缓存区
- 生产者进程每次生产一个进程放入缓存区,消费者进程每次从缓存区取出一个进程并使用
- 只有缓存区没满时,生产者才可以把产品放入缓存区,否则必须等待
- 只有缓冲区不空时,消费者才可以从缓冲区取出产品,否则必须等待
- 缓冲区是临界资源,各进程必须互斥的访问
2.对于问题的解释(不抽象的说法):
我们可以把生产者—消费者问题创造成一个模型:厂家——超市——客户:
- 厂家每次只能生产一个产品,并且需要立刻送到超市,并且占用超市的一个空间,当超市的空间被占满时,厂家无法再生产产品,并且只能等待客户购买产品之后再生产产品。
- 超市的空间是有限的,厂家每送来一个产品,都需要占用超市的一个空间。
- 客户只能在超市有产品时购买产品,不然需要等待厂家生产并运输产品到超市。
- 超市只有一个通道,厂家和客户不能同时对超市进行操作。
3.对于上述模型中信号量的引入:
- 厂家就是问题中的生产者(producer),超市是缓存区(buffer),客户是消费者(consumer)
- 问题中,缓存区的大小为n,可以设置如下信号量:
somaphore empty = n //表示超市(缓存区)的空间为n; somaphore full = 0 //表示超市目前的产品数量为0; - 针对超市的一个通道,即厂家和客户不能同时操作,引入信号量mutex(互斥信号量),当互斥信号量为0时,无法操作,需要等待信号量被释放为1
somaphore mutex = 1
4.PV操作的含义:
1. P操作可以理解为,使用掉请求的一个资源,如: P(empty) = empty-1 2. V操作可以理解为,释放(增加)请求的一个资源,如:V(empty) = empty+1 3. 有时也会使用 wait() 和 signal() ,在实际作用上分别等价于 P() 和 V()
5.生产者——消费者问题PV操作的实现:
对于生产者来说:
他需要先向超市请求一个位置,P(empty) 发现超市有空位并且被他消耗掉之后,再向超市请求使用通道操作,P(mutex) 将产品放入超市之后 让出通道,告诉超市自己操作完了,V(mutex) 超市的产品数+1,V(full)
producer(){
while(1){
P(empty);
P(mutex);
//把产品放入buffer
V(mutex);
V(full);
}
}
对于消费者来说:
他需要先向超市请求一个产品,P(full) 发现超市有产品,自己要过去使用,向超市请求使用通道,P(mutex) 使用完之后 让出通道,V(mutex) 使用了超市的一个产品,那么超市的空间+1,V(empty)
consumer(){
while(1){
P(full);
P(mutex);
//把产品从buffer拿出来
V(mutex);
V(empty);
}
}
|