操作系统——生产者消费者问题
一、问题描述
二、问题分析
该问题中出现的主要的两种关系:
①生产者—消费者之间的同步关系表现为:一旦缓冲池中所有缓冲区均装满产品时,生产者必须等待消费者提供空缓冲区;一旦缓冲池中所有缓冲区全为空时,消费者必须等待生产者提供满缓冲区。
②生产者—消费者之间还有互斥关系:由于缓冲池是临界资源,所以任何进程在对缓冲区进行存取操作时都必须和其他进程互斥进行。
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操作之内呢?其实从逻辑上来说是可以的,比如从缓冲区取出一个产品之后立即使用这个产品,但是这样就会造成临界区的代码量变大,消费者进程访问临界区将会耗费更多的时间,若此时有别的进程想要访问临界区是会被阻塞的,若将这些不是很非代码也放入临界区,会造成进程的并发度降低。
三、重要考点