哲學家就餐問題 C語言講解

2021-09-18 02:16:26 字數 2315 閱讀 1647

原部落格**:哲學家就餐問題-c語言講解

哲學家問題是作業系統中同步互斥的經典問題。通常使用訊號量,管程的方式。這篇文章將會簡要介紹問題的定義和類似服務生解法。並且用c語言實現解法。

問題描述:

五個哲學家圍繞坐在乙個圓形餐桌前,桌上放著五支筷子,每兩個哲學家之間放乙個筷子。哲學家的動作包括就餐和思考。思考不需要拿筷子,而就餐需要拿到兩個筷子才能就餐。兩個相鄰的哲學家需要共享乙個筷子(這個筷子就是乙個共享資源)。

這種情況可能產生死鎖,比如每個哲學家都拿著左手的筷子,永遠都在等右邊的筷子(或者相反)。

如何保證哲學家的動作有序進行,使得總有哲學家能拿到兩個叉子就餐?

在哲學家問題中,哲學家代表著"執行緒",而叉子代表著"共享的物件"(shared object)。哲學家問題在作業系統中的真正含義是"乙個執行緒需要兩個共享的物件來完成一些工作"。

哲學家問題的有兩條互斥前提

當乙個人在進餐時,別人不能偷走這個人的筷子。(難不成從這個人手上搶過去嗎?)

乙個筷子最多只能被乙個人使用。

所以對於乙個哲學家來說,當他餓了的時候,他就要檢查是否有人在使用他需要的筷子,如果有,那麼他等待那人使用完才能獲得需要的筷子。在等待的過程中,他不會放下手上已有的筷子。如果他需要的筷子沒人在使用,他就獲得了指定的筷子。當他結束當前吃的動作(吃了幾口就思考。。。),就放下手上所有的筷子。

上圖用訊號量的方式來保證了互斥條件:chopstick陣列是乙個訊號量陣列,每一訊號量初始值為1(所以稱為binary semaphore,但是在上圖中沒有表現出來),每個哲學家在呼叫take_chopsticks函式時其實是在呼叫訊號量的wait函式:將訊號量減一,如果訊號量運算後的結果小於零則阻塞這個哲學家執行緒。直到獲得了這個筷子的哲學家程序放下筷子,呼叫訊號量post函式喚醒阻塞了的哲學家程序。

如果符合了互斥的要求,可能會出現死鎖的情況:

為了解決哲學家問題中的死鎖情況。我們需要實現同步。

我們可以給哲學家們設定一些"協議"。比如當任意乙個哲學家要進餐時檢查所需筷子是否可用,如果不能夠獲得所有需要的筷子,就放下來。然後隨機等待一段時間。時間到後,繼續嘗試。

我們在上面設定的"協議"還是會出現潛在問題的:所有的哲學家同時拿起右手的筷子,放下計時同一段時間,繼續拿起來。等待。所有哲學家執行緒starvation了(以上的情況發生的可能性看起來是很小,但是放到實際情況,發生的情況還是不算少見的)

隨便設定乙個協議,可能會造成效率低下。或著忙等待。

用訊號量方法來控制筷子滿足互斥條件可能會造成死鎖。

用同步來解決死鎖,還是可能造成忙等待,沒有死鎖,但還是沒有哲學家吃到飯。

所以僅僅是通過訊號量互斥和同步,無法完全解決哲學家問題。

當乙個哲學家在吃飯的時候,與她相鄰的哲學家不能吃飯。

同一時刻,只有乙個哲學家可以檢查是否滿足相鄰兩個哲學家不在吃飯的條件。(在一些解答中用服務員這個概念來表示。餐桌上只有乙個服務員,而且只有服務員有權利指派哲學家拿筷子。服務員只幫哲學家解決餐具的問題,一旦服務的哲學家拿到筷子,服務員就可以服務其他的哲學家)

如果滿足,則該哲學家獲取手邊兩個筷子就餐。其他的哲學家可以開始檢查條件。

如果不滿足,則將自己掛起,等待相鄰的哲學家放下筷子後通知自己。再重複步驟2的檢查過程。

當哲學家用餐結束。放下兩支筷子,通知喚醒相鄰的哲學家。

下圖用訊號量和互斥鎖實現了思路裡描述的過程

//這段**還不能直接執行。think(),wait(),post()和eat()尚未定義。

#define n 5

#define left (n+i-1)%n

#define right (i+1)%n

int state[n]

;/*儲存哲學家狀態的陣列,eating,thinking,hungry*/

semaphore mutex =1;

/*一次只能有乙個哲學家操作儲存哲學家狀態的陣列*/

semaphore p[n]=;

/*哲學家鎖,一開始每個哲學家都不占有資源,所以sema都為0,如果現在乙個哲學家呼叫sema_wait(),會被馬上阻塞*/

void

take_chopsticks

(int i)

void

take_chopsticks

(int i)

void

scheduler

(int i)

}void

philosopher

(int i)

南方科技大學2019春季作業系統課synchronization(2)

理解semaphore及其用法詳解

哲學家就餐問題

三種不同的方式解決『』哲學家就餐『』這個經典的問題

哲學家就餐問題

本文是哲學家就餐問題在 linux 上的程式實現,與windows 平台的實現類似,程式上稍有不同。philosopherdining.cpp include include include include include include rasutil.h using namespace std ...

哲學家就餐問題

pragma once include include include include include include include include include include include include include stdafx.h handle chopstick 5 room l...

哲學家就餐問題

假設有五位哲學家圍坐在一張圓形餐桌旁,做以下兩件事情之一 吃飯,或者思考。吃東西的時候,他們就停止思考,思考的時候也停止吃東西。餐桌中間有一大碗義大利面,每兩個哲學家之間有乙隻餐叉。因為用乙隻餐叉很難吃到義大利面,所以假設哲學家必須用兩隻餐叉吃東西。他們只能使用自己左右手邊的那兩隻餐叉。哲學家就餐問...