1.某寺庙有小和尚、老和尚若干,有一水缸,由小和尚提水入缸供老和尚饮用。水缸可容10桶水,水取自同一井中。水井径窄,每次只能容一个桶取水。水桶总数为3个。每次入缸取水仅为1桶水,且不可同时进行。试给出有关从缸取水、入水的算法描述。
从井中取水并放入水缸是一个连续的动作,可视为一个进程;从缸中取水可视为另一个进程。设水井和水缸为临界资源,引入 well 和 vat:三个水桶无论是从井中取水还是将水倒入水缸都是一次一个,应该给它们一个信号量pail,抢不到水桶的进程只好等待。水缸满时,不可以再放水,设置 empty 信号量来控制入水量;水缸空时,不可以取水,设置 full 信号量来控制。本题需要设置5个信号量来进行控制:
semaphore well=1; //1个水井
semaphore vat=1; //1个水缸
pail=3; //3个水桶
empty=10; //水缸中的剩余空间能容纳的水的桶数,初值为10
full=0; //表示能从水缸中取走的水的桶数,初始水缸没水,处值为0
//小和尚
while(1){
P(empty); //检查水缸里能不能放水
P(pail); //能放水,则拿桶,桶-1
P(well); //到井中打水
从井中打水;
V(well); //打完水,释放“井”互斥资源
P(vat); //将水倒入缸中
将水倒入缸中;
V(vat); //倒完后,释放“水缸”互斥资源
V(full); //缸中水的桶数+1
V(pail); //使用完桶放回,桶+1
}
//老和尚
while(1){
P(full); //检查水缸中是否有水
P(pail); //拿桶装水
P(vat); //使用“水缸”互斥资源
从缸中取水;
V(vat); //释放互斥资源
V(empty); //水缸中的剩余空间+1
喝水;
V(pail); //把桶放回
}
2.如下图所示,三个合作进程P1,P2,P3,它们都需要通过同一设备输入各自的数据a,b,c,该输入设备必须互斥地使用,而且其第一个数据(a)必须由P1进程读取,第二个数据(b)必须由P2进程读取,第三个数据(c)必须由P3进程读取。然后,三个进程分别对输入数据进行下列计算:
最后,P1进程通过所连接的打印机将计算结果x,y,z的值打印出来。请用信号量实现它们的同步。
分析:
进程P1需要用到进程P1读取的a,进程P2读取的b:x=a+b
进程P2需要用到进程P1读取的a,进程P2读取的b:y=a*b
进程P3需要用到进程P2计算的结果y,进程P3读取的数据c,以及进程P1读取的数据a
所以:
P1进程在计算前,需要先确保已经输入了b,其他同理。
这里我们设置S1,S2,S3三个信号量,并将S1初值设为1,S2,S3初值设为0,这样就不用为输入设备专门设置互斥信号量了。但是这样设置就是默认三个进程中P1最先执行。信号量Sb,Sy,Sz分别表示是否已经输入b,以及y,z是否已经计算完成。Sb,Sy,Sz初值为0
P1(){
P(S1); //使用输入设备
输入数据a;
V(S2); //S2+1,表示接下来P2可以使用输入设备
P(Sb); //检查数据b有没有输入
x=a+b;
P(Sy); //检查y是否完成计算
P(Sz); //检查z是否完成计算
使用打印机打印出x,y,z的结果;
}
P2(){
P(S2);
输入数据b;
V(S3); //S3+1,表示接下来P3可以使用输入设备
V(Sb); //表示b已经输入,可以正常进行P(Sb)了
y=a*b;
V(Sy); //Sy已经计算完成,可以正常执行P(Sy)了
}
P3(){
P(P3);
输入数据c;
P(Sy); //检查y是否已经计算完成
z=y+c-a;
V(Sz); //可以执行P(Sz)
}
注意几点:
(1) 为什么P2,P3进程计算之前不需要P(S1)了,因为设置初值的时候我们把P1=1,P1最先执行,数据a最先输入,所以不需要检查数据a有没有输入
(2) 而P1执行时,就需要先检查b是否已经输入,即P(S2),所以进程实际执行的顺序:
① P1进程执行到P(Sb),发现Sb=0,不能继续往下执行
② 执行P2进程,P2进程V(Sb)
③ P1进程继续执行,直到P(Sz),Sz=0,堵塞
④ 执行P3进程,V(Sz)
⑤ P1继续执行
总之就是先V后P,一定要先V资源后,才能P资源
3.有桥如下图所示。车流方向如箭头所示。回答如下问题:
(1)假设桥上每次只能有一辆车行驶,试用信号灯的PV操作实现交通管理。
semaphore bridge=1;
NtoS(){
P(bridge);
通过桥;
V(bridge);
}
StoN(){
P(bridge);
通过桥;
V(bridge);
}
(2)假设桥上不允许两车交会,但允许同方向多辆车一次通过(桥上可有多辆同方向行驶的车)。试用信号灯的PV操作实现桥上的交通管理。
桥上可以同方向多车行驶,需要设置 bridge,还需要对同方向车辆计数。为了防止同方向计数中同时申请 bridge 造成同方向不可同时行车的问题,要对计数过程加以保护,因此设置信号量mutexSN和mutexNS。
int countSN=0; //从南向北的汽车数量
int countNS=0; //从北向南的汽车数量
semaphore mutexSN=1; //保护countSN
semaphore mutexNS=1; //保护countNS
semaphore bridge=1; //互斥信号量
StoN(){ //从南向北的汽车
P(mutexSN);
if(countSN==0)
P(bridge);
countSN++;
V(mutexSN);
过桥;
P(mutexSN);
countSN--;
if(countSN==0)
V(bridge);
V(mutexSN);
}
NtoS(){ //从北向南的汽车
P(mutexNS);
if(countNS==0)
P(bridge);
countNS++;
V(mutexNS);
过桥;
P(mutexNS);
countNS--;
if(countNS==0)
V(bridge);
V(mutexNS);
}
以StoN为例,若这里没有设置mutexSN,如果有多辆自南向北的车同时经过桥,那么都会检测到countSN=0,并且P(bridge),而bridge=1,只有1辆车能申请到bridge,其他车则不能经过桥,达不到题目的要求。
if(countSN==0)
P(bridge);
countSN++;
加入mutexSN:mutexSN=1,若有多辆自南向北的车同时经过桥,一辆车能成功执行P(mutexSN)并申请(bridge),成功记录该车后(countSN++),其他自南向北的车进程就会跳过if判断,不会被堵塞在P(bridge)。
P(mutexSN);
if(countSN==0)
P(bridge);
countSN++;
V(mutexSN);