學習日期:2024.7.9
內容摘要:信號量機制,用信號量實現進程的同步與互斥
信號量機制
信號量的概念
在上節內容中,我們學習了進程互斥的軟件和硬件解決方案,但這些方案都有各自的問題,雙標志法都因為檢查和上鎖兩個步驟不能一氣呵成,會導致兩個進程一起進入臨界區,而Peterson算法和幾個基于硬件實現方式的方法雖然解決了這些問題,但這些方法都會導致忙等。
1965年,荷蘭科學家Dijkstra(就是《數據結構》圖論那位)提出了一種實現進程同步、互斥的方法——信號量機制。
信號量其實就是一個變量(可以是一個整數,也可以是更復雜的數據結構的變量),可以用一個信號量來表示系統中某種資源的數量,比如系統只有一臺打印機,就可以設置一個初始值為1的信號量。
用戶進程可以通過操作系統提供的一對原語來對信號量進行操作,從而很方便的實現進程互斥和同步。
一對原語:wait(S)原語和signal(S)原語,信號量S是函數調用時傳入的一個參數,而wait和signal兩個原語常簡稱為P,V操作(來自荷蘭語proberen和verhogen),簡寫為P(S)和V(S)
整型信號量
用一個整數型的變量作為信號量,用來表示系統中某種資源的變量。
例:假如某系統中有一臺打印機,初始化整型信號量S,S=1。P操作是占用資源,S=S-1,V操作是釋放資源,S=S+1,每次調用之前先判斷S的值,如果S>=1,就P一次,否則等待。
邏輯很簡單,就是用S來計數,因為用了原語實現檢查和上鎖一氣呵成,避免了并發、異步導致的問題。
缺點:還是要利用while結果循環等待,不滿足“讓權等待”原則,沒有解決忙等問題。
記錄型信號量(重點)
整型信號量的缺陷是存在忙等問題,因此人們又提出了記錄型信號量,即用一種記錄型數據結構表示信號量
假如S=2,每次進行一次P操作,S.value--,每次執行一次V操作,S.value++,如果P操作后小于0,進程阻塞,且當S為負時,S.value的絕對值就是正在等待資源的進程的數目。
P操作中一定是先S.value--,之后如果S<0再block;V操作中一定是先S.value++,之后如果S.value<=0再wakeup。注意理解原因!
S.value的初始值表示系統中某種資源的數目,S.value++后<=0,說明有進程在等待資源,因此調用wakeup原語喚醒等待隊列中的第一個進程(被喚醒進程從阻塞態轉換為就緒態)。
S.value==0,資源恰好分配完,S.value==-x,有x個進程正在等待資源。
因為在資源不足時,進程會使用block原語自我阻塞,主動放棄處理機,所以遵循了讓權等待原則,不會出現忙等。
用信號量機制實現進程的同步與互斥
一個信號量對應一種資源,信號量的值=這種資源的剩余數量(信號量的值如果小于0,說明有進程在等待這個資源,絕對值即為等待的進程數)
信號量機制實現進程互斥
1.分析并發進程的關鍵活動,劃分臨界區
2.設置互斥信號量mutex,初始值為1,對不同的臨界資源要設置不同的互斥信號量
3.在進入區P(mutex),申請資源
4.在退出區V(mutex),釋放資源
注意:P,V操作必須要成對出現,申請資源和釋放資源一定會成對出現。
信號量機制實現進程同步
知識回顧:進程同步:讓各并發的進程按照某種我們期望的順序推進。
1.分析什么地方需要同步關系,即分析需要“一前一后”的兩個(或更多)操作
2.設置同步信號量S,初始值為0
3.在“前操作”之后執行V(S)
4.在“后操作”之前執行P(S)
比如說兩個進程A,B,我們希望A先執行,B后執行。此時S代表一個信號,即A已經完成的信號。在A執行完之后,釋放信號,在B執行之前,檢查信號。簡記為“前V后P,前后后前”
如果先執行到B,因為會先進行P(S)操作,此時S--后S=-1,表示此時沒有可用資源,因此P操作中會執行block原語,進程會進入阻塞隊列。當執行完A之后,S++,此時S>=0,就會在V操作中執行wakeup原語,喚醒B進程,這樣就實現了按我們期望的順序推進進程。
感謝您看到這里,如果滿意的話麻煩您點個贊支持一下,個人主頁還有更多內容分享。
內容總結自王道計算機考研《操作系統》 和 人民郵電出版社《操作系統導論》