首先了解一下訊號量吧,訊號量是 e.w.dijkstra 在 1965 年提出的一種方法,它是使用乙個整型變數來累計喚醒的次數,供以後使用。在他的建議中,引入了乙個新的變數型別,稱為訊號量(semaphore),乙個訊號量的取值可以為 0(表示沒有儲存下來的喚醒操作)或者為正值(表示有乙個或多個喚醒操作)。
並且設立了兩種操作:down 和 up(分別為一般化後的 sleep 和 wakeup,其實也是一般教科書上說的 p/v 向量)。對乙個訊號量執行 down 操作,表示檢查其值是否大於 0,如果該值大於 0,則將其值減 1(即用掉乙個儲存的喚醒訊號)並繼續;如果為 0,則程序休眠,而且此時 down 操作並未結束。另外,就是檢查數值,修改變數值以及可能發生的休眠操作都作為單一的,不可分割的 原子操作 來完成。
下面開始考慮用訊號量來解決生產者-消費者問題了,不過在此之前,再次分析一下這個問題的本質會更清晰點:問題的實質在於發給乙個(尚)未休眠程序(如上的消費者程序在只判斷了 count == 0 後即被排程出來,還未休眠)的 wakeup 訊號丟失(如上的生產者程序在判斷了 count == 1 後以為消費者程序休眠,而喚醒它)了。如果它沒有丟失,則一切都會很好。
#define n 100 // 緩衝區中的槽數目
typedef int semaphore; // 訊號量一般被定義為特殊的整型資料
semaphore mutex = 1; // 控制對臨界區的訪問
semaphore empty = n; // 計數緩衝區中的空槽數目
semaphore full = 0; // 計數緩衝區中的滿槽數目
/* 生產者程序 */
void proceducer(void)
}/* 消費者程序 */
void consumer(voi)
}該解決方案使用了三個訊號量:乙個為 full,用來記錄充滿的緩衝槽的數目,乙個為 empty,記錄空的緩衝槽總數,乙個為 mutex,用來確保生產者和消費者不會同時訪問緩衝區。mutex 的初始值為 1,供兩個或者多個程序使用的訊號量,保證同乙個時刻只有乙個程序可以進入臨界區,稱為二元訊號量(binary semaphore)。如果每乙個程序在進入臨界區前都執行乙個 down(...),在剛剛退出臨界區時執行乙個 up(...),就能夠實現互斥。
另外,通常是將 down 和 up 操作作為系統呼叫來實現,而且 os 只需要在執行以下操作時暫時禁止全部中斷:測試訊號量,更新訊號量以及在需要時使某個程序休眠。
這裡使用了三個訊號量,但是它們的目的卻不相同,其中 full 和 empty 用來同步(synchronization),而 mutex 用來實現互斥。
使用訊號量實現生產者 消費者問題
問題描述 使用乙個緩衝區來儲存物品,只有緩衝區沒有滿,生產者才可以放入物品 只有緩衝區不為空,消費者才可以拿走物品。因為緩衝區屬於臨界資源,因此需要使用乙個互斥量 mutex 來控制對緩衝區的互斥訪問。為了同步生產者和消費者的行為,需要記錄緩衝區中物品的數量。數量可以使用訊號量來進行統計,這裡需要使...
Linux訊號量機制(生產者消費者)
該程式為linux訊號量機制實現程式,主要模擬了一般的生產者 消費者問題。生產者 消費者問題是乙個經典的程序同步問題,該問題最早由dijkstra提出,用以演示他提出的訊號量機制。在同乙個程序位址空間內執行的兩個執行緒。生產者執行緒生產物品,然後將物品放置在乙個空緩衝區中供消費者執行緒消費。消費者執...
Linux訊號量機制(生產者消費者)
該程式為linux訊號量機制實現程式,主要模擬了一般的生產者 消費者問題。生產者 消費者問題是乙個經典的程序同步問題,該問題最早由dijkstra提出,用以演示他提出的訊號量機制。在同乙個程序位址空間內執行的兩個執行緒。生產者執行緒生產物品,然後將物品放置在乙個空緩衝區中供消費者執行緒消費。消費者執...