生产者与消费者问题理解(转载+个人理解)
一、问题描述

二、问题分析

该问题中出现的主要的两种关系:
①生产者—消费者之间的同步关系表现为:一旦缓冲池中所有缓冲区均装满产品时,生产者必须等待消费者提供空缓冲区;一旦缓冲池中所有缓冲区全为空时,消费者必须等待生产者提供满缓冲区。
②生产者—消费者之间还有互斥关系:由于缓冲池是临界资源,所以任何进程在对缓冲区进行存取操作时都必须和其他进程互斥进行。
PV操作题目分析的步骤:
1.关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
2.整理思路。根据各进程的操作流程确定PV操作的大致顺序。
3.设置信号量。设置需要的信号量,并根据题目条件确定信号量的初值。(互斥信号量初值一般为1,同步信号量的初值需要看对应资源的初始值是多少)
在这里:


互斥的实现是在同一个进程中进行的一对PV操作。
同步的实现是在两个进程中进行的,在一个进程中执行P操作,在另一个进程中执行V操作。
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操作之后!
我们观察上面的代码,生产者生产产品和消费者使用产品这两个操作都是放在各自进程的PV操作之外的,那么能不能放在各自的PV操作之内呢?其实从逻辑上来说是可以的,比如从缓冲区取出一个产品之后立即使用这个产品,但是这样就会造成临界区的代码量变大,消费者进程访问临界区将会耗费更多的时间,若此时有别的进程想要访问临界区是会被阻塞的,若将这些不是很非代码也放入临界区,会造成进程的并发度降低。
三、期末考题(简单)
试分析下列算法在解决生产者/消费者同步问题时会产生什么后果,并进行改正。设信号量mutex用于生产者与消费者的互斥,初值为1;设avail是生产者的私有信号量,表示缓冲区的空单元数,初值为n;设full是消费者的私有信号量,表示缓冲区中非空单元数,初值为0。(12分)
生产者: 消费者:
begin begin
wait(mutex) wait(mutex)
wait(avail) wait(full)
送数据到缓冲区某单元 取缓冲区某单元数据
signal(full) signal(avail)
signal(mutex) signal(mutex)
end end
按题中的互斥方法有可能导致死锁,例如生产者先拿到操作信号量mutex,但此时缓存区信号量为full,则会导致生产者无法进行后续操作且不会释放信号量mutex,而消费者则始终等待信号量mutex。
改进如下:
生产者: 消费者:
begin begin
wait(avail) wait(full)
wait(mutex) wait(mutex)
送数据到缓冲区某单元 取缓冲区某单元数据
signal(mutex) signal(mutex)
signal(full) signal(avail)
end end
四、利用AND信号量
and信号量可以理解为要么全分配,要么我都不分配。



浙公网安备 33010602011771号