在處理進程間的同步與互斥問題時,我們離不開信號量和PV原語,使用這兩個工具的目的在於打造一段不可分割不可中斷的程序。應當注意的是,信號量和PV原語是解決進程間同步與互斥問題的一種機制,但並不是唯一的機制。
信號量:
信號量的概念1965年由著名的荷蘭計算機科學家 Edsger Wybe Dijkstra 艾茲格·迪科斯徹 提出。
其核心思想是用一種新的變量類型(Semaphore)來記錄可用資源的數量。有兩種實現方式:
1、Semaphore的取值必須大於或等於0。0表示當前已經沒有空閑資源,而正數表示當前空閑資源的數量;
2、Semaphore的取值可正可負,負數的絕對值表示正在等待進入臨界區的進程個數;
信號量是一個二元組(S,Q)。S是一個具有非負初值的整型變量,Q是一個初始狀態為空的隊列。
PV原語
P原語:P是荷蘭語Proberen(測試)的首字母。為阻塞原語,負責把當前進程由運行狀態轉換為阻塞狀態,直到另一個進程喚醒它。具體操作為:申請一個空閑資源(把信號量減1),若成功,則退出;若失敗,則該進程被阻塞。
V原語:V是荷蘭語Verhogen(增加)的首字母。為喚醒原語,負責把一個被阻塞的進程喚醒,他有一個參數表,存放着等待被喚醒的進程信息。具體操作為:釋放一個被占用的資源(把信號量加1),如果發現有被阻塞的進程,則選擇一個喚醒。
表示方法
P(S):表示將信號量S的值減一,即S=S-1;如果S>=0,則該進程繼續執行,否則該進程置為等待狀態,排入等待隊列(隊列Q)。
V(S):表示將信號量S的值加一,即S=S+1;如果S>0,則該進程繼續執行,否則釋放隊列(Q)中第一個等待信號量的進程。
實現互斥模型
在互斥模型中,多個進程對可用資源進行爭用,使用信號量S表示可用資源的數量。一般來說,信號量S>=0時,S表示可用資源的數量。執行一次P操作意味着請求分配一個單位資源,因此S的值減1;當S<0時,表示已經沒有可用資源,請求者必須等待別的進程釋放該類資源,它才能運行下去。而執行一個V操作意味着釋放一個單位資源,因此S的值加1;若S<=0,表示有某些進程正在等待該資源,因此要喚醒一個等待狀態的進程,使之運行下去。
進程互斥是進程之間發生的一種間接性作用,一般是程序不希望的。
如下表所示,我們使用S=1做為初值,表示當前系統資源只有一個,多個進程需要輪流使用這個資源。
在互斥模型的問題中,關鍵的問題在於使用PV操作來保證有限的系統資源被正常的使用和釋放,而不是多人爭搶誰都搶不到,或者某人獨占而不釋放的情況。有點類似於北京現在的搖號制度,實際上資源就是兩萬個號牌,每個申請的人都執行了一次P操作,表示自己想要使用資源,在搖號結果出來之前沒有資源可用,大家都進入Q隊列等候,放號之時,獲得資格的用戶執行V操作,釋放一個等待位置,其他人可以進入下一次的排號等候隊列。
實現同步模型
所謂同步,是指多個相互合作的進程,在一些關鍵點上可能需要相互等待或相互交換信息,這種互相制約的關系稱為進程同步。例如系統中有兩個合作的進程,他們共用一個單緩沖區。這兩個進程一個是計算進程,負責對數據進行計算;另一個為打印進程,負責對計算結果進行打印。當計算進程沒有計算完畢,計算結果沒有送到緩沖區的時候,打印進程就不能打印。一旦計算進程把計算結果送入緩沖區,就應該給打印進程發送一個信號,打印進程收到信號后就可以從緩沖區中取出計算結果進行打印。
之前我在想這個同步模型的時候,考慮可以使用定時輪詢的方式,計算進程定時查詢緩沖區,可用即開始寫入;打印進程定時查詢緩沖區,有內容即開始打印。但是這種沒有相互合作溝通的方式,非常容易出現問題,比如計算進程內容還沒有寫完,打印進程就開始讀取打印,造成分頁的不正確或者數據的不完整。實際上,一般我們都會有多個計算進程,這種情況下就會同時存在資源爭用的問題。
進程同步是進程之間直接的相互作用,是合做進程間有意識的行為。與互斥模型不同,進程同步時的信號量只與制約進程、被制約進程有關而不是與所有的同類並發進程有關,所以同步模型中的信號量為私有信號量。
生產者-消費者模型是同步模型的典型代表,其也存在多種情況,分別敘述如下:
1、一個生產者,一個消費者,共用一個緩沖區。
定義兩個同步信號量,生產者需要一個EMPTY信號量來判斷當前是否能夠寫入,設置初值為1,消費者需要一個FULL信號量,來判斷當前是否能夠讀取,設置初值為0。
2、一個生產者,一個消費者,共用N個緩沖區。
與上面的例子不同的是,EMPTY的初值為N,則生產者的阻塞時間會減少很多。
3、多個生產者,多個消費者,共用N個緩沖區。
在這種場景下,除了同步之外,還需要在生產者之間、消費者之間進行互斥的訪問緩沖區,所以需要設置四個信號量,分別是EMPTY、FULL、生產者之間的互斥信號量Mutex1、消費者之間的互斥信號量Mutex2。
非生產者、消費者模型的例子有一個司機和售票員的。設置RUN信號量供司機判斷是否應該開車,初始值為0;設置STOP信號量供售票員判斷是否可以開門,初始值為0。描述如下:
前驅圖(Precedence Graph)是一種有向無循環圖,記為DAG(Directed Acyclic Graph),用於描述進程間執行的前后關系。如下圖:
圖中的每個結點可用於描述一個進程段或進程,乃至一條語句;結點間的有向邊則用於表示兩個結點之間存在的偏序(Partial Order)或前驅關系。可以使用PV原語,來描述前驅圖。
PS:互斥的問題可以用硬件方法解決,如何解決,不太清楚。
參考資料:
4、百度百科PV原語
5、PV原語
6、PV原語解釋