问题描述
假设“生产者”进程不断向共享缓冲区写人数据(即生产数据),而“消费者”进程不断从共享缓冲区读出数据(即消费数据);共享缓冲区共有n个;任何时刻只能有一个进程可对共享缓冲区(临界区)进行操作。所有生产者和消费者之间要协调,以完成对共享缓冲区的操作。
分析
- 我们可把共享缓冲区中的n个缓冲块视为共享资源,生产者写入数据的缓冲块成为消费者可用资源,而消费者读出数据后的缓冲块 成为生产者的可用资源。为此,可设置三个信号量:full、empty和mutex。其中:full表示有数据的缓冲块数目,初值是0;empty表示无数据的缓冲块数初值是n;mutex用于访问缓冲区时的互斥,初值是1。实际上,full和empty间存在如下关系:full+ empty = N
- 生产者能够生产的前提,就是empty 不为0,当empty为0当然就代表现在不需要生产者出现,只需要消费者尽情数据即可。so 生产者能够进入临界区的前提当然是empty不为0
- 而释放信号量以及对full 变量的控制的顺序也不能调换,假设我们调换了,v(full)后发现full 还是小于0,此时会唤醒等待的消费进程,而无法释放消费进程所需的mutex
代码
buffer: array [0..k-1]of integer;//共享缓冲区的大小
in,out: 0..k-1;//in记录第一个空缓冲区,out记录第一个不空的缓冲区
empty,full,mutex: semaphore;
//empty:无数据的缓冲块,控制缓冲区不满
// full:有数据的缓冲块控制缓冲区不空
// mutex保护临界区
//初始化
empty=k,full=0,mutex=1
cobegin
procedure producer: procedure consumer:
while true then while true then
begin begin
produce(&item); p(full);
p(empty); p(mutex);
p(mutex); item:=buffer[out];
out:=(out+1)mod k;
buffer[in]:=item; v(mutex);
in:=(in+1) mod k; v(empty);
v(mutex); consume(&item);
v(full); end
end
coend