不管是計算機考研、計算機軟件水平考試、計算機操做系統期末考試仍是其餘計算機崗位考試,P、V原語操做都是一個常考點。下面筆者總結了關於P、V操做的一些知識。緩存
信號量是最先出現的用來解決進程同步與互斥問題的機制(也可實現進程通訊),包括一個稱爲信號量的變量及對它進行的兩個原語操做。信號量爲一個整數,咱們設這個信號量爲:sem。很顯然,咱們規定在sem大於等於零的時候表明可供併發進程使用的資源實體數,sem小於零的時候,表示正在等待使用臨界區的進程的個數。根據這個原則,在給信號量附初值的時候,咱們顯然就要設初值大於零。數據結構
p操做和v操做是不可中斷的程序段,稱爲原語。P,V原語中P是荷蘭語的Passeren,至關於英文的pass, V是荷蘭語的Verhoog,至關於英文中的incremnet。併發
且在P,V原語執行期間不容許有中斷的發生。分佈式
對於具體的實現,方法很是多,能夠用硬件實現,也能夠用軟件實現。這種信號量機制必須有公共內存,不能用於分佈式操做系統,這是它最大的弱點。測試
首先應弄清PV操做的含義:PV操做由P操做原語和V操做原語組成(原語是不可中斷的過程),對信號量進行操做,具體定義以下:操作系統
P(S):①將信號量S的值減1,即S=S-1;指針
②若是S>=0,則該進程繼續執行;不然該進程置爲等待狀態,排入等待隊列。blog
V(S):①將信號量S的值加1,即S=S+1;隊列
②若是S>0,則該進程繼續執行;不然釋放隊列中第一個等待信號量的進程。進程
PV操做的意義:咱們用信號量及PV操做來實現進程的同步和互斥。PV操做屬於進程的低級通訊。
什麼是信號量?信號量(semaphore)的數據結構爲一個值和一個指針,指針指向等待該信號量的下一個進程。信號量的值與相應資源的使用狀況有關。當它的值大於0時,表示當前可用資源的數量;當它的值小於0時,其絕對值表示等待使用該資源的進程個數。注意,信號量的值僅能由PV操做來改變。
通常來講,信號量S>=0時,S表示可用資源的數量。執行一次P操做意味着請求分配一個單位資源,所以S的值減1;
當S<0時,表示已經沒有可用資源,請求者必須等待別的進程釋放該類資源,它才能運行下去。而執行一個V操做意味着釋放一個單位資源,所以S的值加1;
若S<=0,表示有某些進程正在等待該資源,所以要喚醒一個等待狀態的進程,使之運行下去
利用信號量和PV操做實現進程互斥的通常模型是:
進程P1 進程P2 …… 進程Pn
…… …… ……
P(S); P(S); P(S);
臨界區; 臨界區; 臨界區;
V(S); V(S); V(S);
…… …… …… ……
其中信號量S用於互斥,初值爲1
使用PV操做實現進程互斥時應該注意的是:
(1)每一個程序中用戶實現互斥的P、V操做必須成對出現,先作P操做,進臨界區,後作V操做,出臨界區。如有多個分支,要認真檢查其成對性。
(2)P、V操做應分別緊靠臨界區的頭尾部,臨界區的代碼應儘量短,不能有死循環。
(3)互斥信號量的初值通常爲1。
利用信號量和PV操做實現進程同步
PV操做是典型的同步機制之一。用一個信號量與一個消息聯繫起來,當信號量的值爲0時,表示指望的消息還沒有產生;當信號量的值非0時,表示指望的消息已經存在。用PV操做實現進程同步時,調用P操做測試消息是否到達,調用V操做發送消息。
利用信號量和PV操做實現進程互斥的通常模型是:
進程A 進程B
.... ....
L: P(信號量) L2:V(信號量)
.... ....
使用PV操做實現進程同步時應該注意的是:
(1)分析進程間的制約關係,肯定信號量種類。在保持進程間有正確的同步關係狀況下,哪一個進程先執行,哪些進程後執行,彼此間經過什麼資源(信號量)進行協調,從而明確要設置哪些信號量。
(2)信號量的初值與相應資源的數量有關,也與P、V操做在程序代碼中出現的位置有關。
(3)同一信號量的P、V操做要成對出現,但它們分別在不一樣的進程代碼中。
【例1】生產者-消費者問題
在多道程序環境下,進程同步是一個十分重要又使人感興趣的問題,而生產者-消費者問題是其中一個有表明性的進程同步問題。下面咱們給出了各類狀況下的生產者-消費者問題,深刻地分析和透徹地理解這個例子,對於全面解決操做系統內的同步、互斥問題將有很大幫助。
(1)一個生產者,一個消費者,公用一個緩衝區。
定義兩個同步信號量:
empty——表示緩衝區是否爲空,初值爲1。
full——表示緩衝區中是否爲滿,初值爲0。
生產者進程
while(TRUE){
生產一個產品;
P(empty);
產品送往Buffer;
V(full);
}
消費者進程
while(TRUE){
P(full);
從Buffer取出一個產品;
V(empty);
消費該產品;
}
(2)一個生產者,一個消費者,公用n個環形緩衝區。
定義兩個同步信號量:
empty——表示緩衝區是否爲空,初值爲n。
full——表示緩衝區中是否爲滿,初值爲0。
設緩衝區的編號爲1~n&61485;1,定義兩個指針in和out,分別是生產者進程和消費者進程使用的指針,指向下一個可用的緩衝區。
生產者進程
while(TRUE){
生產一個產品;
P(empty);
產品送往buffer(in);
in=(in+1)mod n;
V(full);
}
消費者進程
while(TRUE){
P(full);
從buffer(out)中取出產品;
out=(out+1)mod n;
V(empty);
消費該產品;
}
(3)一組生產者,一組消費者,公用n個環形緩衝區
在這個問題中,不只生產者與消費者之間要同步,並且各個生產者之間、各個消費者之間還必須互斥地訪問緩衝區。
定義四個信號量:
empty——表示緩衝區是否爲空,初值爲n。
full——表示緩衝區中是否爲滿,初值爲0。
mutex1——生產者之間的互斥信號量,初值爲1。
mutex2——消費者之間的互斥信號量,初值爲1。
設緩衝區的編號爲1~n&61485;1,定義兩個指針in和out,分別是生產者進程和消費者進程使用的指針,指向下一個可用的緩衝區。
生產者進程
while(TRUE){
生產一個產品;
P(empty);
P(mutex1);
產品送往buffer(in);
in=(in+1)mod n;
V(mutex1);
V(full);
}
消費者進程
while(TRUE){
P(full);
P(mutex2);
從buffer(out)中取出產品;
out=(out+1)mod n;
V(mutex2);
V(empty);
消費該產品;
}
須要注意的是不管在生產者進程中仍是在消費者進程中,兩個P操做的次序不能顛倒。應先執行同步信號量的P操做,而後再執行互斥信號量的P操做,不然可能形成進程死鎖。
【例2】桌上有一空盤,容許存放一隻水果。爸爸可向盤中放蘋果,也可向盤中放桔子,兒子專等吃盤中的桔子,女兒專等吃盤中的蘋果。規定當盤空時一次只能放一隻水果供吃者取用,請用P、V原語實現爸爸、兒子、女兒三個併發進程的同步。
分析在本題中,爸爸、兒子、女兒共用一個盤子,盤中一次只能放一個水果。當盤子爲空時,爸爸可將一個水果放入果盤中。若放入果盤中的是桔子,則容許兒子吃,女兒必須等待;若放入果盤中的是蘋果,則容許女兒吃,兒子必須等待。本題其實是生產者-消費者問題的一種變形。這裏,生產者放入緩衝區的產品有兩類,消費者也有兩類,每類消費者只消費其中固定的一類產品。
解:在本題中,應設置三個信號量S、So、Sa,信號量S表示盤子是否爲空,其初值爲l;信號量So表示盤中是否有桔子,其初值爲0;信號量Sa表示盤中是否有蘋果,其初值爲0。同步描述以下:
int S=1;
int Sa=0;
int So=0;
main()
{
cobegin
father();
son();
daughter();
coend
}
father()
{
while(1)
{
P(S);
將水果放入盤中;
if(放入的是桔子)V(So);
else V(Sa);
}
}
son()
{
while(1)
{
P(So);
從盤中取出桔子;
V(S);
吃桔子;
}
}
daughter()
{
while(1)
{
P(Sa);
從盤中取出蘋果;
V(S);
吃蘋果;
}
}
例題3 設公交車上,司機和售票員的活動以下:司機;啓動車輛;正常行使,到站停車. 售票員;關車門,售票 開車門. 在汽車不斷到站 停車行駛過程當中這兩個活動有什麼同步關係? 用信號量和pv操做實現。
設信號量爲s1(是否開車)和s2(是否停車),s1=1,s2=0;
司機進程: 售票員進程:
begin begin
L1: L2:
P(S1); 關閉車門;
啓動車輛; V(s1);
正常行駛; 售票;
V(s2); P(s2);
goto L1; 開車門;
end; goto L2;
end;
思考題:
四個進程A、B、C、D都要讀一個共享文件F,系統容許多個進程同時讀文件F。但限制是進程A和進程C不能同時讀文件F,進程B和進程D也不能同時讀文件F。爲了使這四個進程併發執行時能按系統要求使用文件,現用PV操做進行管理,請回答下面的問題:
(1)應定義的信號量及初值: 。
(2)在下列的程序中填上適當的P、V操做,以保證它們能正確併發工做:
A() B() C() D()
{ { { {
[1]; [3]; [5]; [7];
read F; read F; read F; read F;
[2]; [4]; [6]; [8];
} } } }
思考題解答:
(1)定義二個信號量S一、S2,初值均爲1,即:S1=1,S2=1。其中進程A和C使用信號量S1,進程B和D使用信號量S2。
(2)從[1]到[8]分別爲:P(S1) V(S1) P(S2) V(S2) P(S1) V(S1) P(S2) V(S2)
信號量、PV操做是解決進程間的同步與互斥問題的。
★ 作題時尤爲要注意隱藏的同步、互斥問題。這些問題一般能夠納入生產者-消費者問題和閱讀者-寫入者問題。
★ PV操做必定是成對出現的,可是這不意味着它會在一個進程內成對出現。
★ 在互斥關係中,PV操做必定是在一個進程內成對出現。並且,信號必定大於0,具體多少視狀況而定。而對於同步關係,則一對PV操做在兩個進程或者更多的進程中出現。
★ 對於同步關係,信號量可能爲0,也可能不爲0;用於同步的信號個數可能1個,也多是多個。
★ 對信號量爲1的,應該先執行V操做。
★ 在生產者-消費者問題中,要設置三個信號量:empty-空閒的緩存區數量,初值爲n;full-已填充的緩存區數量,初值爲0;mutex-保證只有一個進程在寫入緩存區,初值爲1。
★ 在閱讀者-寫入者問題中,設置兩個信號量:信號量access-控制寫入互斥,初值爲1;信號量rc-控制對共享變量ReadCount(讀者統計值)的互斥訪問。