题20
题目
【2014 统考真题】系统中有多个生产者进程和多个消费者进程, 共享一个能存放 1000 件产品的环形缓冲区 (初始为空)。
缓冲区未满时, 生产者进程可以放入其生产的一件产品, 否则等待;
缓冲区未空时, 消费者进程可从缓冲区取走一件产品, 否则等待。
要求一个消费者进程从缓冲区连续取出 10 件产品后, 其他消费者进程才可以取产品。
请使用信号量P, V (wait (),signal())操作实现进程间的互斥与同步, 要求写出完整的过程, 并说明所用信号量的含义和初值。
分析
题20

我感觉还是只用维护一个empty和full,只是需要给解mutex锁额外补一个条件,就是一个消费者进程从缓冲区连续取出 10 件产品后, 其他消费者进程才可以取产品,其他的和生产者-消费者问题,我认为没有什么区别
注意:这里这个解锁条件,是在消费者内部的,因为有多个消费者,必须在消费者内部定义这个计数器,把它维护成消费者中的mutex,应该是不可以硬编码实现的
上面的逻辑有问题,为了防止多个消费者之间竞争,应该在消费者内部维护一把锁mutex,保证每次都只有一个人在读缓冲区,count可以不用变量维护,直接硬编码
semaphore mutex = 1, empty = 1000, full = 0, count = 10, othe_mutex=1; //这个计数器其实也可以不用变量维护,直接硬编码,应该也可以
// 生产者进程
void producer( i ) {
while(1) {
//生产产品
P(empty); //获取空位
//如果有空位,解锁开始生产
P(mutex); //锁住缓冲区
//放入产品
V(mutex); //解锁缓冲区
V(full); //释放产品
}
}
void error_comsumer(i) {
while(1) {
//先防止其他进程读缓冲区
P(othe_mutex);
//检查有没有东西能消费
P(full);
//如果有东西可以消费,就开始消费
P(mutex);
//连续读10次,才能让其他人读
for(int i = 0; i < 10; i++) {
//从缓冲区取出产品
}
}
}
//上面这么写是错的,每次读也都要检查full,for循环应该是一个大循环
void consumer(i) {
while(1) {
//防止其他进程读缓冲区
P(othe_mutex);
//开始读10次
for(int i = 0; i < 10; i++) {
//检查有没有东西能消费
P(full);
//如果有东西可以消费,就开始消费
P(mutex);
//从缓冲区取出产品
V(mutex);
V(empty);
}
}
//放掉消费者的锁,让其他消费者可以读缓冲区
V(othe_mutex);
}解
这是典型的生产者和消费者问题, 只对典型问题加了一个条件, 只需在标准模型上新加一个信号量, 即可完成指定要求。
设置 4 个变量 mutex1, mutex2, empty 和 full, mutex1 用于控制一个消费者进程在一个周期(10 次) 内对缓冲区的访问,初值为 1 ;
mutex2 用于控制进程单次互斥地访问缓冲区,初值为 1 ;
empty 代表缓冲区的空位数, 初值为 1000 ;
full 代表缓冲区的产品数, 初值为 0 , 具体进程描述如下:
// 用于实现生产者之间的互斥
semaphore mutex1 = 1;
// 用于实现消费者之间的互斥
semaphore mutex2 = 1;
// 空缓冲区数
semaphore empty = 1000;
// 非空缓冲区数
semaphore full = 0;
// 生产者进程
producer() {
while (1) {
// 生产一个产品
P(empty);
P(mutex2);
// 把产品放入缓冲区
V(mutex2);
V(full);
}
}
// 消费者进程
consumer() {
while (1) {
P(mutex1); // 连续取 10 次
for (int i = 0; i < 10; i++) {
P(full); // 判断缓冲区是否有产品
P(mutex2); // 互斥访问缓冲区
// 从缓冲区取出一件产品
V(mutex2); // 互斥访问缓冲区
V(empty); // 腾出一个空位
// 消费这件产品
}
V(mutex1);
}
}