本文記錄9道PV問題的解,不保證正確,僅供參考,,
1、 有一個倉庫,可以存放 A 和 B 兩種產品,倉庫的存儲空間足夠大,但要求:
( 1)一次只能存入一種產品( A 或 B);
( 2) -N < (A 產品數量-B 產品數量) < M。
其中, N 和 M 是正整數。試用“存放 A”和“存放 B”以及 P、 V 操作描述產品 A 與
產品 B 的入庫過程。
1 Semaphore mutex = 1; //互斥信號量 2 Semaphore a = M-1 ; //存放A的資源信號量,初值為M-1 3 Semaphore b = N-1; //存放B的資源信號量,初值為N-1 4 存放 A: 5 { 6 while(true) 7 { 8 Get A; 9 P(&a); 10 P(&mutex); 11 Put A; 12 V(&mutex); 13 V(&b); 14 } 15 } 16 存放B: 17 { 18 while(true) 19 { 20 Get B; 21 P(&b); 22 P(&mutex); 23 Put B; 24 V(&mutex); 25 V(&a); 26 } 27 }
2、 桌子上有一只盤子,最多可容納兩個水果,每次只能放入或取出一個水果。爸爸專向盤
子放蘋果( apple),媽媽專向盤子中放桔子( orange);兩個兒子專等吃盤子中的桔子,
兩個女兒專等吃盤子中的蘋果。請用 P、 V 操作來實現爸爸、媽媽、兒子、女兒之間的
同步與互斥關系。
1 Semaphore mutex = 1; //互斥信號量, 其初值為1 2 Semaphore empty = 2; //記錄允許向盤子中放入水果的個數,初值為2 3 Semaphore orange = 0; //盤子中已放入的蘋果的個數,初值為0 4 Semaphore apple = 0; //盤子中已放入的桔子的個數,初值為0 5 main() 6 { 7 Cobegin 8 { 9 father //父親進程 10 { 11 while (true) 12 { 13 P(empty); //減少盤中可放入的水果數 14 P(mutex); //申請向盤中取、放水果 15 向盤中放蘋果; 16 V(mutex); //允許向盤中取、放水果 17 V(apple); //遞增盤中的蘋果數 18 } 19 } 20 mother //母親進程 21 { 22 while (true) 23 { 24 P(empty); //減少盤中可放入的水果數 25 P(mutex); //申請向盤中取、放水果 26 向盤中放桔子; 27 V(mutex); //允許向盤中取、放水果 28 V(orange); //遞增盤中的桔子數 29 } 30 } 31 daughteri(i=1,2) //兩女兒進程 32 { 33 while (true) 34 { 35 P(apple); //減少盤中蘋果數 36 P(mutex); //申請向盤中取、放水果 37 取盤中蘋果; 38 V(mutex); //允許向盤中取、放水果 39 V(empty); //遞增盤中可放入的水果數 40 } 41 } 42 sonj(j=1,2) //兩兒子進程 43 { 44 while (true) 45 { 46 P(orange); //減少盤中桔子數 47 P(mutex); //申請向盤中取、放水果 48 取盤中桔子; 49 V(mutex); //允許向盤中取、放水果 50 V(empty); //遞增盤中可放入的水果數 51 } 52 } 53 } 54 Coend 55 }
3、 有一個理發師,一把理發椅和 N 把供等候理發的顧客坐的椅子。如果沒有顧客,則理發
師便在理發師椅子上睡覺;當一個顧客到來時,必須喚醒理發師進行理發;如果理發師
正在理發時又有顧客來到,則如果有空椅子可坐,他就坐下來等,如果沒有空椅子,他
就離開。為理發師和顧客各編一段程序(偽代碼)描述他們的行為,要求不能帶有競爭
條件。
1 Semaphore mutex = 1; //互斥信號量,初值為1. 2 Semaphore Wait = 0; //等待服務的顧客數 3 Semaphore barbers= 0; //等待顧客的理發師數 4 Int custNum = 0; //等待的顧客(還沒理發的) 5 6 Costumer() 7 { 8 while(true) 9 { 10 P(mutex); //申請理發 11 if(custNum>0) 12 { 13 if(custNum<N) //若等待人數小於N 14 { 15 V(mutex); //釋放進程等待 16 CustNum++; //增加等待人數 17 } 18 else //若等待人數超過N 19 { 20 V(mutex); //釋放進程等待 21 離開; 22 } 23 } 24 else //若目前無人等待 25 { 26 V(mutex); //釋放進程等待 27 V(barbers); //如果必要的話,喚醒理發師 28 理發; 29 離開; 30 P(mutex); //要求進程等待 31 custNum--; //顧客人數減1 32 V(mutex); //釋放進程等待 33 V(wait); //等待人數減1 34 } 35 } 36 } 37 38 Barber() 39 { 40 while(true) 41 { 42 P(mutex); //要求進程等待 43 if(custNum ==0) //目前無顧客 44 { 45 V(mutex); //釋放進程等待 46 P(barbers); //理發師睡覺 47 } 48 else 49 { 50 V(mutex); //釋放進程等待 51 理發; 52 } 53 } 54 }
4、 吸煙者問題。三個吸煙者在一間房間內,還有一個香煙供應者。為了制造並抽掉香煙,
每個吸煙者需要三樣東西:煙草、紙和火柴。供應者有豐富的貨物提供。三個吸煙者中,
第一個有自己的煙草,第二個有自己的紙,第三個有自己的火柴。供應者將兩樣東西放
在桌子上,允許一個吸煙者進行對健康不利的吸煙。當吸煙者完成吸煙后喚醒供應者,
供應者再放兩樣東西(隨機地)在桌面上,然后喚醒另一個吸煙者。試為吸煙者和供應
者編寫程序解決問題。
1 Semaphore S = 1; //供應者 2 Semaphore S1,S2,S3; //三個吸煙者 3 S1 = S2 = S3 = 0; 4 bool flag1,flag2,fiag3; //三種吸煙原料 5 fiag1=flag2=flag3=true; 6 7 Apply() //供應者 8 { 9 While(true) 10 { 11 P(S); 12 取兩樣香煙原料放桌上,由flagi標記; 13 if (flag2 && flag3) //供紙和火柴 14 { 15 V(S1); //喚醒吸煙者一 16 } 17 else if(flag1 && fiag3) //供煙草和火柴 18 { 19 V(S2); //喚醒吸煙者二 20 } 21 else //供煙草和紙 22 { 23 V(S3); //喚醒吸煙者三 24 } 25 } 26 } 27 28 Smoker1() //吸煙者一 29 { 30 While(true) 31 { 32 P(S1); 33 取原料; 34 做香煙; 35 V(S); //喚醒供應者 36 吸香煙; 37 } 38 } 39 40 smoker2() //吸煙者二 41 { 42 While(true) 43 { 44 P(S2); 45 取原料; 46 做香煙; 47 V(S); //喚醒供應者 48 吸香煙; 49 } 50 } 51 52 Smoker3() //吸煙者三 53 { 54 While(true) 55 { 56 P(S3); 57 取原料; 58 做香煙; 59 V(S); //喚醒供應者 60 吸香煙; 61 } 62 }
5、 面包師問題。面包師有很多面包和蛋糕,由 n 個銷售人員銷售。每個顧客進店后先取
一個號,並且等着叫號。當一個銷售人員空閑下來,就叫下一個號。請分別編寫銷售人
員和顧客進程的程序。
1 Semaphore buyer= 0; //顧客人數 2 Semaphore seller = n; //銷售人員數 3 Semaphore mutex_s = 1; //用於銷售人員的互斥信號量 4 Semaphore mutex_b = 1; //用於顧客的互斥信號量 5 int count_s = 0; //記錄取號的值 6 int count_b = 0; //記錄叫號的值 7 8 void Buy() //顧客進程 9 { 10 進店; 11 P(mutex_b); //取號 12 count_b++; 13 V(mutex_b); 14 V(buyer); 15 P(seller); //等待叫號 16 買面包; 17 離開 18 } 19 20 void Sell() 21 { 22 while(true) 23 { 24 P(buyer); 25 P(mutex_s); //叫號 26 count_s++; 27 叫編號為count_s的顧客; 28 V(mutex_s); 29 V(seller); 30 } 31 }
6、 桌上有一空盤,運行存放一只水果,爸爸可向盤中放蘋果,也可放桔子,兒子專等吃盤
中的桔子,女兒專等吃盤中的蘋果。規定當盤中空時一次只能放一個水果供吃者取用,
用 P,V 原語實現爸爸兒子和女兒 3 個並發進程的同步。
1 Semaphore S = 1; //S 表示盤子是否為空; 2 Semaphore Sa = 0; //Sa 表示盤中是否有蘋果; 3 Semaphore Sb = 0; //Sb 表示盤中是否有桔子; 4 5 Father() //父親進程 6 { 7 while(TRUE) 8 { 9 P(S); 10 將水果放入盤中; 11 if (放入的是桔子) 12 V(Sb); 13 else 14 V(Sa); 15 } 16 } 17 18 Son() //兒子進程 19 { 20 while(TRUE) 21 { 22 P(Sb); 23 從盤中取出桔子; 24 V(S); 25 吃桔子; 26 } 27 } 28 29 Daughter() //女兒進程 30 { 31 while(TRUE) 32 { 33 P(Sa); 34 從盤中取出蘋果; 35 V(S); 36 吃蘋果; 37 } 38 }
7、 寫者優先的讀者--寫者問題。讀者-寫者問題為數據庫訪問建立了一個模型。例如,一
個系統,其中有許多競爭的進程試圖讀寫其中的數據,多個進程同時讀是可以接受的,但如
果一個進程正在更新數據庫,則所有的其他進程都不能訪問數據庫,即使讀操作也不行。
寫者優先是指當一個寫者到達時,將阻止其后面的讀者進入數據庫,直到其離開為止。
1 Semaphore Mut1, Mut2, Wmutex, Fmutex; //互斥信號量 2 int Rcount, Wcount; //讀寫者人數 3 Mut1 = Mut2 = WMutex = Fmutex = 1; 4 Rcount = Wcount = 0; 5 6 Writer() //寫者進程 7 { 8 While(true) 9 { 10 P(Mut1); 11 Wcount=Wcount+1; 12 If (Wcount==1) 13 { 14 P(Fmutex); //如有讀者,寫者阻塞在此處 15 } 16 V(Mut1); 17 P(WMutex); 18 寫; 19 V(Wmutex); 20 P(Mut1); 21 Wcount=Wcount-1; 22 If (Wcount==0) 23 { 24 V(Fmutex); 25 } 26 V(Mut1); 27 } 28 } 29 30 Reader() //讀者進程 31 { 32 While(true) 33 { 34 P(Mut2); 35 Rcount=Rcount+1; 36 If (Rcount==1) 37 { 38 P(Fmutex); 39 } 40 V(Mut2); 41 讀; 42 P(Mut2); 43 Rcount=Rcount-1; 44 If (Rcount==0) 45 { 46 V(Fmutex); 47 } 48 V(Mut2); 49 } 50 }
8、 在天津大學與南開大學之間有一條彎曲的小路,這條路上每次每個方向上只允許一輛自
行車通過。但其中有一個小的安全島 M,同時允許兩輛自行車停留,可供兩輛自行車已
從兩端進入小路的情況下錯車使用。如圖所示。
下面的算法可以使來往的自行車均可順利通過。其中使用了 4 個信號量, T 代表天大路
口資源, S 代表南開路口資源, L 代表從天大到安全島一段路的資源, K 代表從南開到
安全島一段路的資源。程序如下,請在空白位置處填寫適當的 PV 操作語句,每處空白
可能包含若干個 PV 操作語句。
1 begin 2 t:=1;s:=1;l:=1;k:=1; 3 cobegin 4 從天大到南開的進程 5 begin 6 ______(1)______ 7 通過 L 路段; 8 進入安全島 M; 9 ______(2)______ 10 通過 K 路段 11 ______(3)______ 12 end 13 從南開到天大的進程 14 begin 15 略,與“從天大到南開的進程”相反。 16 end 17 coend 18 end
解答:
(1) P(t); P(l);
(2) V(l); P(k);
(3) V(k); V(t);
9、 三個進程 P1、 P2、 P3 互斥使用一個包含 N(N>0)個單元的緩沖區。 P1 每次用 produce()
生成一個正整數並用 put()送入緩沖區某一空單元中;P2 每次用 getodd()從該緩沖區中
取出一個奇數並用 countodd()統計奇數個數;P3 每次用 geteven()從該緩沖區中取出一
個偶數並用 counteven()統計偶數個數。請用信號量機制實現這三個進程的同步與互斥活
動,並說明所定義信號量的含義。要求用偽代碼描述。
1 P1() 2 { 3 While(true) 4 { 5 X = produce(); //生成一個數 6 P(empty); //是否有空單元格 7 P(mutex); //進入臨界區 8 Put(); 9 if(X%2 == 0) 10 V(s2); //如果是偶數,向P3發出信號 11 else 12 V(s1); //如果是奇數,向P2發出信號 13 V(mutex); //離開臨界區,釋放互斥信號量 14 } 15 } 16 17 P2() 18 { 19 While(true) 20 { 21 P(s1); //收到P1發送來的信號,已產生奇數 22 P(mutex); //進入臨界區 23 getodd(); 24 countodd():=countodd()+1; 25 V(mutex); 26 V(empty); //離開臨界區,釋放互斥信號量 27 } 28 } 29 30 P3() 31 { 32 While(true) 33 { 34 P(s2) //收到P1發送來的信號,已產生偶數 35 P(mutex); //進入臨界區 36 geteven(); 37 counteven():=counteven()+1; 38 V(mutex); 39 V(empty); //離開臨界區,釋放互斥信號量 40 } 41 }