3.在某超市里有一個收銀員,且同時最多允許有n個顧客購物,我們可以將顧客和收銀員看成是兩類不同的進程,且工作流程如下圖所示。為了利用PV操作正確地協調這兩類進程之間的工作,設置了三個信號量S1、S2和Sn,且初值分別為0、0和n。這樣圖中的a應填寫__(1)__,圖中的b1、b2應分別填寫__(2)__,圖中的c1、c2應分別填寫__(3)__。
500){this.resized=true;this.style.width=500;}" resized="true">
(1) A. P(S1) B.P(S2) C.P(Sn) D.P(Sn)、P(S1)
(2) A.P(Sn)、V(S2) B.P(Sn)、V(S1) C.P(S2)、V(S1) D.V(S1)、P(S2)
(3) A.P(S1)、V(S2) B.P(Sn)、V(S1) C.P(S2)、V(S1) D. V(S1)、 P(S2)
答案:(1)C (2)D (3)A
解析:這是一道考查PV操作的題,所以首先得弄清楚那些地方需要互斥、那些地方需要同步。題目中給出了兩類進程:顧客進程與收銀元進程,由于超市是顧客進程之間的公有資源,而且超市里限制最多允許有n個顧客購物,所以要設置一個公有信號量Sn,初值是n,顧客進程在進入超市時要執行P(Sn),離開超市時要執行V(Sn)操作。顧客購物后要到收銀員處付款,因此顧客進程與收銀員進程之間是同步的關系,一次只允許一個顧客進程付款,整個超市只有一個收銀員進程收費,所以需要為顧客進程設置一個私有信號量S2,為收銀員進程設置一個私有信號量S1,由于開始時沒有顧客去付款,收銀員也沒有收費,所以S1和S2的初值為0。當有顧客買完東西去付款時執行V(S1),通知收銀員進程有顧客付款,此時收銀員進程執行P(S1)操作后就可進入收費,收費完成后收銀元進程執行V(S2),以通知顧客收費完畢,此時顧客執行P(S2)就可離開收銀臺,在離開超市時需執行V(Sn),釋放資源。
復習提示:PV操作在操作系統中處于很重要得地位,要想合適的運用PV操作,必須很好的理解進程之間的互斥與同步,即那些進程之間是互斥的,那些進程之間是同步的。
2005年上半年程序員試題
●某系統中有一個緩沖區,進程P1不斷地生產產品送入緩沖區,進程P2不斷地從緩沖區取產品消費。假設該緩沖區只能容納一個產品。進程P1與P2的同步模型如下圖所示:
(這個圖就是教程中常見的那個圖)
P1 P2
__| __|
| 生產一個產品 | P(S2)
| P(S1) | 從緩沖區取一個產品
| 產品送緩沖區 | V(S1)
| V(S2) | 消費
|__| |__|
為此,應設信號量S1的初值為__(18)__,信號量S2的初值為__(19)__。
(18) A.-2 B.-1 C.0 D.1
(19) A.-2 B.-1 C.0 D.1
答案:(18)D (19)C
分析:
資源S是這個資源初始狀態擁有的數目,也就是沒有任何操作,剛開始的時候資源的可用數。
簡單的例子,一個盤子可以放8個蘋果,一次只能一個人拿一個蘋果或者放一個蘋果,則設置兩個資源S1、S2分別表示盤子中蘋果的數量和取放蘋果的許可,則S1初始值為8,S2為1。
以下一定要記住:
P操作
S = S-1
S<0 阻塞
V操作
S= S+1
S 〈=0 喚醒
S1、S2分別是P1、P2對緩沖區操作的開關,S1=1表示初始狀態P1進程可以對緩沖區進行操作,而對于S2=0正好阻止了P2進程對緩沖區的操作!在剛開始的時候緩沖區為空,其允許P1在其中放入產品,但不能讓P2取出產品,所以才產生這樣的結果
P一次什么什么就減一個。如果你P的玩意是0.那P下面的東西就不開工了。
V 一次什么就加一次
這個同步有s1 s2.
s1肯定是為1的。緩沖區可以放幾個東西就應該是幾.
你P了p1 一次以后。 代表向緩沖區里放了東西。s1 = 0了。表示緩沖區不能放東西了。進程時并行了。假設這句執行完了后跳到第二個程序中去。是p(s2) 剛肯定不行。所以s2一定要為初始要為0. 要等待第一個放進緩沖區的事做完后V(s2)把s2標志位搞醒
●某倉庫有兩名發貨員,一名審核員。當顧客提貨時,只要發貨員空閑,允許顧客進入倉庫提貨,顧客離開時,審核員檢驗顧客提貨是否正確。其工作流程如下圖所示。為了利用PV操作正確地協調他們之間的工作,設置了兩個信號量S1和S2,且S1的初值為2,S2的初值為1。圖中的a應填寫____(25)___;圖中的b、c和d應分別填寫____(26)____。
500){this.resized=true;this.style.width=500;}">
供選擇的答案:
(25)A.P(S1) B.P(S2) C.V(S1) D.V(S2)
(26)A.P(S2)、V(S2)和V(S1) B.P(S1)、V(S1)和V(S2)
C.V(S1)、P(S2)和V(S2) D.V(S2)、P(S1)和V(S1)
分析:
顧客來了,要看看是否有發貨員.即發貨員資源是否存在.
所以用P(S1) 若S1>0表示,存在(無論多少)
若S1<=0表示,不存在,進程阻塞.
提完貨.這說明,肯定用發貨員了.肯定還有人等著提貨.這時,應該釋放發貨員.
所以用V(S1)
然后,要審貨.
可能有人正在審呢,所以用P(S2)意思和上面相同.
審完貨.要釋放,可能有人正等著審呢.所以用V(S2)釋放審貨員.
完畢.
PV原語實現進程間互斥與同步
PV原語的含義
P操作和V操作是不可中斷的程序段,稱為原語。PV原語及信號量的概念都是由荷蘭科學家E.W.Dijkstra提出的。信號量sem是一整數,sem大于等于零時代表可供并發進程使用的資源實體數,但sem小于零時則表示正在等待使用臨界區的進程數。
P原語操作的動作是:
(1)sem減1;
(2)若sem減1后仍大于或等于零,則進程繼續執行;
(3)若sem減1后小于零,則該進程被阻塞后進入與該信號相對應的隊列中,然后轉進程調度。
V原語操作的動作是:
(1)sem加1;
(2)若相加結果大于零,則進程繼續執行;
(3)若相加結果小于或等于零,則從該信號的等待隊列中喚醒一等待進程,然后再返回原進程繼續執行或轉進程調度。
PV操作對于每一個進程來說,都只能進行一次,而且必須成對使用。在PV原語執行期間不允許有中斷的發生。
用PV原語實現進程的互斥
由于用于互斥的信號量sem與所有的并發進程有關,所以稱之為公有信號量。公有信號量的值反映了公有資源的數量。只要把臨界區置于P(sem)和V(sem)之間,即可實現進程間的互斥。就象火車中的每節車廂只有一個衛生間,該車廂的所有旅客共享這個公有資源:衛生間,所以旅客間必須互斥進入衛生間,只要把衛生間放在P(sem)和V(sem)之間,就可以到達互斥的效果。以下例子說明進程的互斥實現。
例1
生產圍棋的工人不小心把相等數量的黑子和白子混裝載一個箱子里,現要用自動分揀系統把黑子和白子分開,該系統由兩個并發執行的進程組成,功能如下:
(1)進程A專門揀黑子,進程B專門揀白子;
(2)每個進程每次只揀一個子,當一個進程在揀子時不允許另一個進程去揀子;
分析:
第一步:確定進程間的關系。由功能(2)可知進程之間是互斥的關系。
第二步:確定信號量及其值。由于進程A和進程B要互斥進入箱子去揀棋子,箱子是兩個進程的公有資源,所以設置一個信號量s,其值取決于公有資源的數目,由于箱子只有一個,s的初值就設為1。
實現:
begin
s:semaphore;
s:=1;
cobegin
process A
begin
L1: P(s);
揀黑子;
V(s);
goto L1;
end;
process B
begin
L2:P(s);
揀白子;
V(s);
goto L2;
end;
coend;
end;
判斷進程間是否互斥,關鍵是看進程間是否共享某一公有資源,一個公有資源與一個信號量相對應。確定信號量的值是一個關鍵點,它代表了可用資源實體數。如下實例:
例2
某車站售票廳,任何時刻最多可容納20名購票者進入,當售票廳中少于20名購票者時,廳外的購票者可立即進入,否則需要在外面等待。每個購票者可看成一個進程。
分析:第一步:確定進程間的關系。售票廳是各進程共享的公有資源,當售票廳中多于20名購票者時,廳外的購票者需要在外面等待。所以進程間是互斥的關系。第二步:確定信號量及其值。只有一個公有資源:售票廳,所以設置一個信號量s。售票廳最多容納20個進程,即可用資源實體數為20,s的初值就設為20。
實現:
begin
s:semaphore;
s:=20;
cobegin
process PI(I=1,2,……)
begin P(s);
進入售票廳;
購票;
退出;
V(s);
end;
coend
當購票者進入售票廳前要執行P(s)操作,執行后若s大于或等于零,說明售票廳的人數還未滿可進入。執行后若s小于零,則說明售票廳的人數已滿不能進入。這個實現中同時最多允許20個進程進入售票廳購票,其余進程只能等待。
用PV原語實現進程的同步
與進程互斥不同,進程同步時的信號量只與制約進程及被制約進程有關而不是與整組并發進程有關,所以稱該信號量為私有信號量。利用PV原語實現進程同步的方法是:首先判斷進程間的關系為同步的,且為各并發進程設置私有信號量,然后為私有信號量賦初值,最后利用PV原語和私有信號量規定各進程的執行順序。下面我們將例1增添一個條件,使其成為進程間是同步的。
例3
在例1的基礎之上再添加一個功能:
(3)當一個進程揀了一個棋子(黑子或白子)以后,必讓另一個進程揀一個棋子(黑子或白子)。
分析:
第一步:確定進程間的關系。由功能(1)(2)(3)可知,進程間的關系為同步關系。第二步:確定信號量及其值。進程A和B共享箱子這個公有資源,但規定兩個進程必須輪流去取不同色的棋子,因而相互間要互通消息。對于進程A可設置一個私有信號量s1,該私有信號量用于判斷進程A是否能去揀黑子,初值為1。對于進程B同樣設置一個私有信號量s2,該私有信號量用于判斷進程B是否能去揀白子,初值為0。當然你也可以設置s1初值為0,s2初值為1。
實現:
begin
s1,s2:semaphore;
s1:=1;s2:=0;
cobegin
process A
begin
L1: P(s1);
揀黑子;
V(s2);
goto L1;
end;
process B
begin
L2:P(s2);
揀白子;
V(s1);
goto L2;
end;
coend;
end;
另外一個問題就是P原語是不是一定在V原語的前面?回答是否定的。下面看一個例子。
例4
設在公共汽車上,司機和售票員的活動分別是:司機:啟動車輛,正常行車,到站停車。售票員:上乘客,關車門,售票,開車門,下乘客。用PV操作對其控制。
分析:
第一步:確定進程間的關系。司機到站停車后,售票員方可工作。同樣,售票員關車門后,司機才能工作。所以司機與售票員之間是一種同步關系。
第二步:確定信號量及其值。由于司機與售票員之間要互通消息,司機進程設置一個私有信號量run,用于判斷司機能否進行工作,初值為0。售票員進程設置一個私有信號量stop,用于判斷是否停車,售票員是否能夠開車門,初值為0。
實現:
begin stop ,run:semaphore
stop:=0;run:=0;
cobegin
driver: begin
L1: P(run);
啟動車輛;
正常行車;
到站停車;
V(stop);
goto L1;
end;
conductor:begin
L2:上乘客;
關車門;
V(run);
售票;
P(stop);
開車門;
下乘客;
goto L2;
end;
coend;
end;
用PV操作還可以實現進程同步與互斥的混合問題,典型的如:多個生產者和多個消費者共享容量為n的緩存區。這個例子在很多書中都有介紹,在這里就不說了。