操作系統原理之經典PV問題


本文記錄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+112        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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM