1.今有一个文件F供进程共享,现把这些进程分为A、B两组,规定同组的进程可以同时读文件F;但当有A组(或B组)的进程在读文件F时就不允许B组(或A组)的进程读文件F。试用P、V操作(记录型信号量)来进行管理。
这是读者-写者问题变形,文件F在A与B之间要进行互斥,设信号量Fmutex用来两组间互斥,显然每组的读者要进行计数,来说明有木有某组在读文件,需要2个计数变量c1和c2,再设信号量Asem和Bsem分别对2个计数变量c1和c2进行互斥访问。
Semaphore Fmutex=1,Asem=0,Bsem=0;
int c1=c2=0;
Cobegin
Pa(i=1,2,3...){
P(Asem)
c1++;
if(c1==1)P(Fmutex)
V(Asem)
reading F;
P(Asem)
c1--;
if(c1==0)V(Fmutex)
V(Asem)
}
Pb(i=1,2,3...){
P(Bsem)
c2++;
if(c2==1)P(Fmutex)
V(Bsem)
reading F;
P(Bsem)
c2--;
if(c2==0)V(Fmutex)
V(Bsem)
}
coend
2.过双道十字路口问题。
这个问题是读者-写着问题的变形,路口要在水平和垂直方向上进行互斥,但在p1和p3方向上不需要互斥;同样p2和p4方向上也不需要互斥。因此可以设p1和p3为一组,p2和p4为一组。设信号量mutex用来两组间互斥。每组上来车要进行计数,需要2个计数变量c1和c2,再设信号量sem13和sem24分别对2个计数变量c1和c2进行互斥访问。
Semaphore mutex=1,sem13=1,sem24=1;
int c1=2=0;
cobegin
p1(){
P(sem13)
c1++;
if(c1=1) P(mutex)
V(sem13)
P1通过路口;
P(sem13)
c1--;
if(c1==0)V(mutex)
V(sem13)
}
p2(){
P(sem24)
c2++;
if(c2==1)P(mutex)
V(sem24)
P2通过路口;
P(sem24)
c2--;
if(c2==0)V(mutex)
V(sem24)
}
p3(){
P(sem13)
c1++;
if(c1=1) P(mutex)
V(sem13)
P3通过路口;
P(sem13)
c1--;
if(c1==0)V(mutex)
V(sem13)
}
p4(){
P(sem24)
c2++;
if(c2==1)P(mutex)
V(sem24)
P4通过路口;
P(sem24)
c2--;
if(c2==0)V(mutex)
V(sem24)
}
coend
3.吃水果问题:桌上有一只盘子,每次只能放一个水果,爸爸专向盘中放苹果,妈妈专向盘中放桔子,儿子专等吃盘里的桔子,女儿专等吃盘里的苹果。只要盘子空,则爸爸或妈妈可向盘中放水果,仅当盘中有自己需要的水果时,儿子或女儿可从中取出,请给出四人之间的同步关系,并用P、V操作实现四人正确活动的程序。
父亲和母亲先放水果,儿子女儿再取水果;父亲与女儿,母亲与儿子是一个同步关系,父亲与母亲要竞争空盘子,但空盘子容量为2.
设信号量m1表示盘子空位,信号量m2表示儿子是否能取苹果,m3表示女儿能否取桔子。
int m1=2,m2=0,m3=0;
cobegin
p1(){
while(1){
洗桔子;
P(m1);
放桔子;
V(m3);
}
}
p2(){
while(1){
洗苹果;
P(m1);
放苹果;
V(m2);
}
}
p3(){
while(1){
P(m2);
取苹果;
V(m1);
吃苹果;
}
}
p4(){
while(1){
P(m3);
取桔子;
V(m1);
吃桔子;
}
}
coend
4.试利用记录型信号量写出一个不会出现死锁的哲学家进餐问题的算法。
解法一:
semaphore Chopstick[5],5;
chopstick[0].value=chopstick[1].value=1;
chopstick[2].value=chopstick[3].value=1;
chopstick[4].value=1;
S.value=4;//最多允许4个哲学家同时拿筷子
process Pi()(i=0,1,2,3,4){//第i个哲学家进程
while(true){
wait(5);//看是否允许拿筷子
wait(chopstick[i]);//拿起左边筷子
wait(chopstick[(i+1)%5]);//拿起右边筷子
eating;
signal(chopstick[i]);//放下左边筷子
signal(chopstick[(i+1)%5]);//放下右边筷子
signal(5);
thinking;
}
}
parbegin//进程并发执行
P0();
P1();
P2();
P3();
P4();
parend
解法二:奇数号哲学家先拿左边筷子,然后再拿右边筷子;偶数号哲学家先拿右边筷子,然后再拿左边筷子。
semaphore chopstick[5];
chopstick[0].value=chopstick[1].value=1;
chopstick[2].value=chopstick[3].value=1;
chopstick[4].value=1;
parbegin
process Pi()(i=0,2,4){
while(true){
wait(chopstick[(i+1)%5]);
wait(chopstick[i]);
eating;
signal(chopstick[(i+1)%5]);
signal(chopstick[i]);
thinking;
}
}
process Pi()(i=1,2){
while(true){
wait(chopstick[i]);
wait(chopstick[i+1]);
eating;
signal(chopstick[i]);
signal(chopstick[i+1]);
thinking;
}
}
parend