6.假设缓冲区buf1和缓冲区buf2无限大,进程p1向buf1写数据,进程p2向buf2写数据,要求buf1数据个数和buf2数据个数的差保持在(m,n)之间(m<n,m,n都是正数).
分析:题中没有给出两个进程执行顺序之间的制约关系,只给出了一个数量上的制约关系,即m<=|buf1数据个数-buf2数据个数|<=n.不需要考虑缓冲区的大小,只需要考虑两个进程的同步和互斥.p2向buf2写数据比p1向buf1写数据的次数最少不超过m次,最多不能超过n次,反之也成立.所以是一个生产者和消费者问题。
将等式展开得:(1)m<=(buf1数据个数-buf2数据个数)<=n; (2)m<=(buf2数据个数-buf1数据个数)<=n;由于m,n都是正数,等式只有一个成立,不妨设(1)成立.在进程p1和p2都没有运行时,两个缓冲区数据个数之差为0,因此,p1必须先运行,向buf1至少写m+1个数据后再唤醒p2运行.信号量s1表示p1一次写入的最大量,初值为n,s2表示p2一次写入的最大量,初值为-m.
begin
var mutex1=1,mutex2=1,s1=n,s2=-m:semaphore;
cobegin
process p1
begin
repeat
get data;
p(s1);
p(mutex1);
写数据到buf1;
v(mutex1);
v(s2);
end
process p2
begin
repeat;
get data;
p(s2);
p(mutex2);
写数据到buf2;
v(mutex2);
v(s1);
end
coend
end
注:p1和p2每次执行时需要进行一些额外的操作.对于p2来说,它首先必须在自己的缓冲区buf2中写入至少m个数据,此后p1和p2的同步可简单通过两个信号量来控制.题目的一个变形是要求:-m<=(buf2数据个数-buf1数据个数)<=n;那么信号量的初值就变成m和n,若只有p1向buf1放入数据而p2不放入数据到buf2中,则p1最多可放m次.因此,设置信号量s1,初值为m,此外,每当p2放入一个数据到buf2中时,则使信号量s1增1,即p1增加一次放入数据到buf1的机会.反之,若只有p2向buf2放入数据而p1不放入数据到buf1中,则p2最多可放次.因此,设置信号量s2,初值为n,此外,每当p1放入一个数据到buf1中时,则使信号量s2增1,即p2增加一次放入数据到buf1的机会.
![](/Images/OutliningIndicators/None.gif)
begin
var mutex1=1,mutex2=1,s1=m,s2=n:semaphore;
cobegin
process p1
begin
repeat
get data;
p(s1);
p(mutex1);
写数据到buf1;
v(mutex1);
v(s2);//p1每放入一个数据到buf1同时使s2增加1
end
process p2
begin
repeat;
get data;
p(s2);
p(mutex2);
写数据到buf2;
v(mutex2);
v(s1);//p2每放入一个数据到buf2同时使s1增加1
end
coend
end
7,两人公用一个账号,每次限存或取10元;
![](/Images/OutliningIndicators/None.gif)
begin
var mutex=1:semaphore;
amount =0:integer;
cobegin
process save
m1: integer;
begin
repeat
p(mutex);
m1= amount ;
m1 = m1 +10;
amout = m1;
v(mutex);
end
process take
m2: integer;
begin
repeat;
p(mutex);
m2= amount ;
m2 = m2 -10;
amout = m2;
v(mutex);
end
coend
end
8,有个盘子,可以容纳两个水果,每次只能放入或取出一个水果,爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,两个儿子专等吃橘子,两个女儿专等吃苹果.
分析:盘子是临界资源,而爸爸和妈妈可以同时向其中放水果,因此要设置一个互斥信号量mutex.盘子最多容纳两个水果,因此,要对放入盘子的水果进行计数,就是要设置一个信号量empty,初值为2.由于盘子可以放两个水果,即当盘子里有一个水果时,存在即可以放也可以取的情况,因此,除了对放水果进行互斥外,对取水果也要互斥.此外,爸爸和女儿,妈妈和儿子之间存在同步关系,要设置信号量apple和orange实现同步,初值都是0.
![](/Images/OutliningIndicators/None.gif)
begin
var mutex=1,empty =2,apple = 0,orange = 0:semaphore;
cobegin
process father
begin
repeat
p(empty );
p(mutex);
放入苹果;
v(mutex);
v(apple);
end
process mother
begin
repeat
p(empty );
p(mutex);
放入橘子;
v(mutex);
v(orange);
end
process son-i(i=1,2)
begin
repeat
p(orange);
p(mutex);
取橘子;
v(mutex);
v(empty);
end
process daughter-i(i=1,2)
begin
repeat
p(apple);
p(mutex);
取苹果;
v(mutex);
v(empty);
end
coend
end
注:要注意盘子的容量,当盘子的容量大于1时,不仅要考虑同步,还要考虑互斥.变形后:一个盘子,可以放一个水果,爸爸放苹果,妈妈放香蕉,一个儿子专等吃香蕉,一个女儿专等吃苹果.
begin
var mutex=1,apple = 0,banana= 0:semaphore;
cobegin
process father
begin
repeat
p(mutex);
放入苹果;
v(apple);
end
process mother
begin
repeat
p(mutex);
放入香蕉;
v(banana);
end
process son
begin
repeat
p(banana);
取香蕉;
v(mutex);
end
process daughter
begin
repeat
p(apple);
取苹果;
v(mutex);
end
coend
end
9.银行有n个柜员,每个顾客进入银行后先取一个号,并且等着叫号,当一个柜员空闲后,就叫下一个号.
分析:将顾客号码排成一个队列,顾客进入银行领取号码后,将号码由队尾插入;柜员空闲时,从队首取得顾客号码,并且为这个顾客服务,由于队列为若干进程共享,所以需要互斥.柜员空闲时,若有顾客,就叫下一个顾客为之服务.因此,需要设置一个信号量来记录等待服务的顾客数.
begin
var mutex=1,customer_count=0:semaphore;
cobegin
process customer
begin
repeat
取号码;
p(mutex);
进入队列;
v(mutex);
v(customer_count);
end
![](/Images/OutliningIndicators/None.gif)
process serversi(i=1
n)
begin
repeat
p(customer_count);
p(mutex);
从队列中取下一个号码;
v(mutex);
为该号码持有者服务;
end
coend
end