總結寫在前面:程序員
1.注意設置的信號量的初值。算法
2.無論如何變,只要緊緊的抓住同步和互斥來分析問題。編程
3.先靠濾同步狀況即全部「等待」狀況。有幾個「等待」信號量類型就有幾個。windows
4. 接下來靠濾要互斥處理的資源。安全
先講講PV操做的起源和用法。多線程
1962,荷蘭學者Dijksrta在參與X8計算機的開發中設計並實現了具備多道程序運行能力的操做系統——THE Multiprogramming System。爲了解決這個操做系統中進程(線程)的同步與互斥問題,他巧妙地利用火車運行控制系統中的「信號燈」(semaphore,或叫「信號量」)概念加以解決。信號量的值大於0時,表示當前可用資源的數量;當它的值小於0時,其絕對值表示等待使用該資源的進程個數。注意,這個信號量的值僅能由PV操做來改變。併發
PV操做由P操做原語和V操做原語組成(原語也叫原子操做Atomic Operation,是不可中斷的過程),對信號量(注意不要和Windows中的信號量機制相混淆)進行操做,具體定義以下:spa
P(S):操作系統
①將信號量S的值減1,即S=S-1;.net
②若是S>=0,則該進程繼續執行;不然該進程置爲等待狀態。
V(S):
①將信號量S的值加1,即S=S+1;
②該進程繼續執行;若是該信號的等待隊列中有等待進程就喚醒一等待進程。
用PV操做實現多線程的同步與互斥是很是簡單的,只要靠慮邏輯處理上合理嚴密而不用靠慮具體技術細節,所以與寫僞代碼較爲類似。好比有多個進程P1、P2、 ……PN。它們要互斥的訪問一個資源。用PV操做來實現就很是方便直觀。下面是PV操做代碼:
設置信號量爲S,初值爲1。各進程的操做流程以下:
進程P1 進程P2 …… 進程Pn
P(S); P(S); P(S);
訪問資源; 訪問資源; 訪問資源;
V(S); V(S); V(S);
能夠看出PV操做會忽略具體的編程細節,讓程序員的主要精力放在線程同步互斥的邏輯處理上。所以,經過練習PV操做能快速有效提升程序員對多線程的邏輯思惟能力,達到強化「內功」的目的。
第一題 放水果 南京大學計算機研真題
桌上有一空盤,容許存放一隻水果。爸爸可向盤中放蘋果,也可向盤中放桔子,兒子專等吃盤中的桔子,女兒專等吃盤中的蘋果。規定當盤空時一次只能放一隻水果供吃者取用,請用P、V原語實現爸爸、兒子、女兒三個併發進程的同步。
這個題目涉及的東西很是之多,光人物就有三個再加水果,盤子等等,確實讓人感受好像無從下手。但無論題目如何變,只要緊緊的抓住同步和互斥來分析問題就一定能迎刃而解。
下面先靠慮同步狀況即全部「等待」狀況:
第一.爸爸要等待盤子爲空。
第二.兒子要等待盤中水果是桔子。
第三.女兒要等待盤中水果是蘋果。
接下來來靠慮要互斥處理的資源,看起來盤子好像是要做互斥處理的,但因爲題目中的爸爸、兒子、女兒均只有一個,而且他們訪問盤子的條件都不同,因此他們根本不會同時去訪問盤子,所以盤子也就不用做互斥處理了。分析至些,這個題目已經沒有難度了,下面用PV原語給出:
先設置三個信號量,信號量Orange表示盤中有桔子,初值爲0。信號量Apple表示盤中有蘋果,初值爲0。信號量EmptyDish表示盤子爲空,初值爲1。三我的的操做流程以下所示:
1.爸爸
P(EmptyDish)
if (rand()%2==0)
{
放桔子
V(Orange)
}
else
{
放蘋果
V(Apple)
}
2.兒子
P(Orange)
取桔子
V(EmptyDish)
3.女兒
P(Apple)
取蘋果
V(EmptyDish)
第二題 安全島 南開大學研真題
在南開大學至天津大學間有一條彎曲的路,每次只容許一輛自行車經過,但中間有小的安全島M(同時容許兩輛車),可供兩輛車在已進入兩端小車錯車,設計算法並使用P,V實現。
這個問題應該如何靠慮了?一樣只要緊緊的抓住同步和互斥來分析問題就一定能迎刃而解。
靠慮全部「等待」狀況:
在路口N準備從N到T的人應該何時進入了?若是他只判斷道路K上有沒有人確定是不行的,由於若是安全島M上已經有2我的,那麼路口N和路口T再各進一人,確定會形成死鎖。所以能夠這樣——在路口N準備從N到T的人要等待與他同方向的人已經到達T,若是此人已經到達T,且道路K上沒有人,他一定能夠上路了。同理在路口T準備從T到N的人也應該這樣作。
再靠慮互斥狀況:
路上每次只容許一輛自行車經過,因此道路是須要做互斥處理的。
分析以後,下面就用PV原語給出:
設置信號量NT表示在路口N且從N到T方向上容許出發的自行車數量,初值爲1。信號量TN表示在路口T且從T到N方向上容許出發的自行車數量,初值爲1。信號量K和L表示道路,初值均爲1。這樣從N到T的車和從T到N的車的行駛流程以下:
從N到T的車 從T到N的車
P(NT) P(TN)
P(K) P(L)
由N到M 由T到M
V(K) V(L)
P(L) P(K)
由M到T 由M到T
V(L) V(K)
V(NT) V(TN)
這個題目的解法有不少,好比還能夠用信號量M來記錄安全島M上空位個數,初值爲2。每一個進入道路前的人都要先預訂安全島上的空位,訂到後再互斥的進入道路。不然就要等待安全島上有空位。信號量K和L表示道路,初值均爲1。而後從N到T的車和從T到N的車的行駛流程以下:
從N到T的車 從T到N的車
P(M) P(M)
P(K) P(L)
由N到M 由T到M
V(K) V(L)
P(L) P(K)
V(M) V(M)
由M到T 由M到T
V(L) V(K)
這種解決方法也是不會形成死鎖的。安全島的解法很是之多,網上還有很多不一樣的解法,有興趣的童鞋能夠搜索一下。