哲學家進餐問題

哲學家進餐問題

產生背景

由荷蘭學者Dijkstra提出的哲學家進餐問題(The Dinning Philosophers Problem)是經典的同步問題之一。哲學家進餐問題是一大類並發控制問題的典型例子,涉及信號量機制、管程機制以及死鎖等作業系統中關鍵問題的套用,在作業系統文化史上具有非常重要的地位。對該問題的剖析有助於深刻地理解計算機系統中的資源共享進程同步機制、死鎖等問題,並能熟練地將該問題的解決思想套用於生活中的控制流程。

問題描述

n哲學家進餐問題描述有五個哲學家,他們的生活方式是交替地進行思考和進餐,n哲學家們共用一張圓桌,分別坐在周圍的五張椅子上,在圓桌上有五個碗和五支筷子,n平時哲學家進行思考,飢餓時便試圖取其左、右最靠近他的筷子,只有在他拿到兩支筷子時才能進餐,n進餐完畢,放下筷子又繼續思考。

約束條件

(1)只有拿到兩隻筷子時,哲學家才能吃飯。
(2)如果筷子已被別人拿走,則必須等別人吃完之後才能拿到筷子。
(3)任一哲學家在自己未拿到兩隻筷子吃飯前,不會放下手中拿到的筷子。

信號量機制

筷子是臨界資源,一段時間只允許一位哲學家使用。為了表示互斥,用一個信號量表示一隻筷子,五個信號量構成信號量數組。本文中算法用類C語言描述偽碼算法。算法描述如下:n用五支筷子的信號量構成信號量數組:
Semaphore chopstick[5]={1,l,1,l,1};
p(stick[i]);
p(stick[(i+1) % 5]);
進餐;
v(stick[i]);
v(stick[(i+1) % 5]);
思考;
當哲學家飢餓時,總是先去拿他左邊的筷子,執行wait(chopstick[I]),成功後,再去拿他右邊的筷子,執行wait(chopstick[I+1]%5);成功後便可進餐。進餐畢,先放下他左邊的筷子,然後再放下右邊的筷子。當五個哲學家同時去取他左邊的筷子,每人拿到一隻筷子且不釋放,即五個哲學家只得無限等待下去,引起死鎖。

死鎖問題的解決

(1)破壞請求保持條件
利用原子思想完成。即只有拿起兩支筷子的哲學家才可以進餐,否則,一支筷子也不拿。
解法一:利用AND機制實現第1位哲學家的活動描述為:
philosopher (int I)
{
while(true)
{
思考;
swait(chopstick[(I+1)]%5,chopstick[I]);
進餐;
Ssignal(chopstick[I],chopstick[(I+i)%5]);
}
}
解法二:利用記錄型信號量機制實現在初始化中增加一個信號量定義:semaphore mutex=1:
第1位哲學家的活動描述:
philosopher (int I)
{
while(true)
{
思考;
wait(mutex);
wait(stiCk[I]);
wait(Stick[(I+1)%5]);
Signal(mutex);
進餐;
signal(stick[I]);
Signal(Stick[(I+1)%5]);
}
}
該方法將拿兩隻筷子的過程作為臨界資源,一次只允許一個哲學家進入。
(2)破壞環路等待條件
在上述死鎖問題中,哲學家對筷子資源的申請構成了有向環路,如圖2所示。
圖2環路等待
解法一:奇數號哲學家先拿他左邊的筷子,偶數號哲學家先拿他右邊的筷子。這樣破壞了同方向環路,一個哲學家拿到一隻筷子後,就阻止了他鄰座的一個哲學家吃飯。按此規定,將是1、2號哲學家競爭I號筷子;3、4號哲學家競爭4號筷子。兩種算法描述如下:
1)第1個哲學家的活動:
philosopher (int I)
{
while(true)
{
思考;
If I%2==1 then
wait(Stick[I]);
wait(stick[(I+1)%5]);
進餐;
Signal(stick[I J);
signal(stick[(I+1)%5]);
e1Se
wait(stick[(I+1)%5]);
wait(stick[I]);
進餐;
signal(stick[(I+1)%5]);
Signal(stick[I]);
}
}
(2)第1個哲學家的活動:
philosopher(int I)
{
while(true)
{
思考;
wait(chopstick[I+(I%2)];
wait(chopstick[(I+(I+1)%2)%5])
進餐;
signal(chopstick[I+(I%2)]);
Signal(chopstick[(I+(I+1)%2)%5]);
}
}
解法二:至多允許四位哲學家進餐,將最後一個哲學家停止申請資源,斷開環路。最終能保證有一位哲學家能進餐,用完釋放兩隻筷子,從而使更多的哲學家能夠進餐。增加一個信號量定義semaphore count=4:算法描述第1個哲學家的活動:
philosopher (int I)
{
while(true)
思考;
wait(count);
wait(chopstiok[I]);
wait(chopstick[I+1]mod 5);
進餐;
signal(chopstick[I]);
signal(chopstick[I+1]mod 5)
signal(count);
}
}
解法三:哲學家申請資源總是按照資源序號先大後小的順序,這樣0.3號哲學家先右後左,但是4號哲學家
先左後右,改變方向,破壞了環路。算法描述第1個哲學家的活動:
philosopher(int I)
{
while(true)
{
思考;
if I>(I+1)%5 then
wait(chopstick[I]);
wait(chopstick[I+1]mod 5);
else
wait(chopstick[T+1]mod 5);
wait(chopstick[T]);/*哲學家總是先取最
大序號的筷子*/
進餐;
signal(chopstick[I]);
signal(chopstick[I+1]mod5);
}
}

管程機制

在用信號量機制解決同步問題時,往往比較繁瑣,採用面向對象的思想,將資源及資源的共享操作封裝起來,用管程來管理,實現哲學家進餐問題,使用起來更加方便。
算法實現描述如下:
1)建立管程
monitor PC
{
semaphore chopstick[5]=11,1,1,1,1);
X:condition;/*定義條件變數*/
void Get:(int T) /*定義取筷子過程*/
{
Tf chopstick[I]=1 and chopstick[(i+1)%5]=1 then
get the chopstick[I]and chopstick[(i+1)%5];
else X.wait;/*左右筷子沒有,則等待*/
)
void Put(int i) /*定義放下筷子過程*/
{
put:the chopstick[I]and chopstick
(i+1)%5];
Tf X.quene then X.signal;/*喚醒等待筷子的哲學家*/
)
}
2)使用管程
第1個哲學家的活動:
void philosopher(int I)
{
while(true)
{
思考;
get:(I);
進餐;
put(I);
}
}

相關詞條

相關搜尋

熱門詞條

聯絡我們