[OS]利用信號量實現進程同步與互斥
PV操作問題分析步驟
1.關系分析。找出題目中描述的各個進程,分析它們之間的同步、互斥關系。
2.整理思路。根據各進程的操作流程確定P、V操作的大致順序。
經典問題
1.生產者-消費者問題
描述
系統中有一組生產者進程和一組消費者進程,生產者進程每次生產一個產品放入緩沖區,消費者進程每次從緩沖區中取出一個產品並使用。(注:這里的“產品”理解為某種數據)
條件分析
生產者、消費者共享一個初始為空、大小為n的緩沖區。
只有緩沖區沒滿時,生產者才能把產品放入緩沖區,否則必須等待。
只有緩沖區不空時,消費者才能從中取出產品,否則必須等待。
緩沖區是臨界資源,各進程必須互斥地訪問。
思路
*顛倒相鄰P操作順序會出現死鎖 V操作順序可以顛倒
2.多生產者-多消費者問題
描述
桌子上有一只盤子,每次只能向其中放入一個水果。爸爸專向盤子中放蘋果,媽媽專向盤子中放橘子,兒子專等着吃盤子中的橘子,女兒專等着吃盤子中的蘋果。只有盤子空時,爸爸或媽媽才可向盤子中放一個水果。僅當盤子中有自己需要的水果時,兒子或女兒可以從盤子中取出水果。
條件分析
互斥關系:
對緩沖區(盤子)的訪問要互斥地進行
同步關系(一前一后):
1.父親將蘋果放入盤子后,女兒才能取蘋果
2.母親將橘子放入盤子后,兒子才能取橘子
3.只有盤子為空時,父親或母親才能放入水果
*“盤子為空”這個事件可以由兒子或女兒觸發,事件發生后才允許父親或母親放水果
思路
*這里要注意如果緩沖區為1,有可能可以不需要設置mutex互斥信號量,但若緩沖區大於1,必須設置以防止同時訪問導致數據覆蓋
3.吸煙者問題
描述
假設一個系統有三個抽煙者進程和一個供應者進程。
每個抽煙者不停地卷煙並抽掉它,但是要卷起並抽掉一支煙,抽煙者需要有三種材料:煙草、紙和膠水。三個抽煙者中,第一個擁有煙草第二個擁有紙、第三個擁有膠水。
供應者進程無限地提供三種材料,供應者每次將兩種材料放桌子上,擁有剩下那種材料的抽煙者卷一根煙並抽掉它,並給供應者進程一個信號告訴完成了,供應者就會放另外兩種材料再桌上,這個過程一直重復(讓三個抽煙者輪流地抽煙)
條件分析
本質上這題也屬於“生產者消費者”問題,更詳細的說應該是“可生產多種產品的單生產者一多消費者”。
桌子可以抽象為容量為1的緩沖區,要互斥訪問。
組合一:紙+膠水;組合二:煙草+膠水;組合三:煙草+紙。
同步關系(從事件的角度來分析):
桌上有組合一→第一個抽煙者取走東西;
桌上有組合二→第二個抽煙者取走東西;
桌上有組合三→第三個抽煙者取走東西;
發出完成信號→供應者將下一個組合放到桌上。
思路
4.讀者寫者問題
描述
有讀者和寫者兩組並發進程,共享一個文件,當兩個或兩個以上的讀進程同時訪問共享數據時不會產生副作用,但若某個寫進程和其他進程(讀進程或寫進程)同時訪問共享數據時則可能導致數據不一致的錯誤。因此要求:
①允許多個讀者可以同時對文件執行讀操作;
②只允許一個寫者往文件中寫信息:
③任一寫者在完成寫操作之前不允許其他讀者或寫者工作;
④寫者執行寫操作前,應讓已有的讀者和寫者全部退出。
條件分析
兩類進程:寫進程、讀進程。
互斥關系:寫進程一寫進程、寫進程一讀進程。
讀進程與讀進程不存在互斥問題。
思路
*可增加信號量實現寫優先(防止寫進程飢餓),如下
5.哲學家進餐問題
描述
一張圓桌上坐着5名哲學家,每兩個哲學家之間的桌上擺一根筷子,桌子的中間是一碗米飯。哲學家們傾注畢生的精力用於思考和進餐,哲學家在思考時,並不影響他人。只有當哲學家飢餓時,才試圖拿起左、右兩根筷子(一根一根地拿起)。如果筷子已在他人手上,則需等待。飢餓的哲學家只有同時拿起兩根筷子才可以開始進餐,當進餐完畢后,放下筷子繼續思考。
條件分析
1.關系分析:系統中有5個哲學家進程,5位哲學家與左右鄰居對其中間筷子的訪問是互斥關系。
2.整理思路:這個問題中只有互斥關系,但與之前遇到的問題不同的事,每個哲學家進程需要同時持有兩個臨界資源才能開始吃飯。如何避免臨界資源分配不當造成的死鎖現象,是哲學家問題的精髓。
3.信號量設置:定義互斥信號量數組chopstick[5]={1,1,1,1,1}用於實現對5個筷子的互斥訪問。並對哲學家按0~4編號,哲學家i左邊的筷子編號為i,右邊的筷子編號為(i+1)%5。
如何防止死鎖的發生呢?
①可以對哲學家進程施加一些限制條件,比如最多允許四個哲學家同時進餐。這樣可以保證至少有一個哲學家是可以拿到左右兩只筷子的。
②要求奇數號哲學家先拿左邊的筷子,然后再拿右邊的筷子,而偶數號哲學家剛好相反。用這種方法可以保證如果相鄰的兩個奇偶號哲學家都想吃飯,那么只會有其中一個可以拿起第一只筷子,另一個會直接阻塞。這就避免了占有一支后再等待另一只的情況。