问题 多项选择题

有n个生产者进程向1个有限的缓冲区不断地发送信息,这些信息通过缓冲区分发到m个消费者,缓冲区的大小只可以存放1条信息。生产者和消费者的工作遵循如下规则:
(1)生产者和消费者对缓冲区的访问互斥;
(2)对每1条放入缓冲区的信息,所有消费者都必须接收1次;
(3)缓冲区满时,生产者必须阻塞,缓冲区空时,消费者阻塞。
请用信号量和P、V操作组织正确的发送和接收。用类C语言进行描述。

答案

参考答案:本题的解答采用分离的信号量来实现,可以比较清楚地看到操作的过程。
typedef int semaphore; //定义信号量
semaphore mutex; //缓冲区互斥信号量用于读写互斥
semaphore empty[m]={A,A,…,A}; //当前缓冲区所有格子为空
semaphore grid[m]={0,0,…,0); //缓冲区的每个格子满的信号量
void producer( ) //生产者
{ int i, buffer;
while(A) //并发调度
{ message=produce( ); //生产者生产信息
for(i=0, i<m, i++) //生产者必须
P(empty[m]); //等待所有格子为空
P(mutex); //取得缓冲区互斥量
buffer = write(message); //将数据写入缓冲区
V(mutex); //释放缓冲区互斥量
for(i=0, i<m, i++) //写者写入一次
V(grid[i]); //所有格子信号量增一
}
}
Void consumer(k, ptr) //第k个消费者
{ int i, buffer;
while(A) //并发调度
{ P(grid[k]); //对应第k个消费者是否可取数据
P(mutex); //取得缓冲区互斥量
ptr = read(buffer); //消费者读取消息送到本进程空间
V(mutex); //释放缓冲区互斥量
V(empty[k]); //将本消费者的空信号量增一
consume( ); //消费者消费消息
}
}

解析: 本题是经典的生产者和消费者问题的变形。在经典的生产者和消费者的模型中,生产者和消费者共用一组缓冲区,生产者向缓冲区中写入一次数据,消费者从缓冲区中读出一次数据,即写一次,读一次。本题中,生产者向缓冲区中只写一次,但是每个消费者却都要读一次。对于此类问题,可以把缓冲区看成是m格的缓冲区阵列,这样一来,生产者每写一次缓冲区,相当于填满了一块m格的缓冲区,而消费者只需要读出属于自己格子的信息即可,当所有的格子读空以后,这个缓冲区就可以接纳下一个生产者的写入。分析清楚其工作机制,可以从经典的生产者和消费者问题出发,来设计相应的信号量。信号量的设计可以是信号量组,也可以采用分离的信号量来实现。
在编程中,注意进程间的并发,while(1)的语句不可省略。当然,生产者和消费者的题目是非常经典的题目,变化也很多,上例只是一个简单的变化。更复杂的变化可以是让缓冲区不止存放一条信息,这样的题目变化更多,答案也更多,考生可以参阅相关的资料来完成。

名词解释
名词解释