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