前言:
當一位哲學家思考時,他與其他同事不交流德频。時而,他會感到饑餓缩幸,并試圖拿起與他相近的兩根筷子(筷子在他和他的左或右鄰居之間)壹置。一個哲學家一次只能拿起一根筷子。顯然表谊,他不能從其他哲學家手里拿走筷子钞护。當一個饑餓的哲學家同時擁有兩根筷子時,他就能吃爆办。在吃完后难咕,他會放下兩根筷子,并開始思考距辆。
哲學家就餐問題是一個經(jīng)典的同步問題余佃,這不是因為其本身的實際重要性,也不是因為計算機科學家不喜歡哲學家跨算,而是因為它是大量并發(fā)控制問題的一個例子爆土。這個代表型的例子滿足:在多個進程之間分配多個資源,而且不會出現(xiàn)死鎖和饑餓诸蚕。
哲學家進餐問題:
(一)問題:
5個哲學家圍坐在一個圓桌上步势,每兩個哲學家之間都有一只筷子氧猬,哲學家平時進行思考,只有當他們饑餓時坏瘩,才拿起筷子吃飯盅抚。
規(guī)定每個哲學家只能先取其左邊筷子,然后取其右邊筷子倔矾,然后才可以吃飯泉哈。
(二)分析:
每一只筷子都是一個臨界資源,設(shè)置5個互斥信號量破讨。
Semaphore stcik[5]={1,1,1,1,1}
因為:只有占有左邊筷子-》占有右邊筷子-》吃飯
所以p(左邊筷子)-》p(右邊筷子)-》吃飯
(三)實現(xiàn):
main(){
philosopher(0);//注意不可以用循環(huán),因為此中是4個并列的進程奕纫。
philosopher(1);
philosopher(2);
philosopher(3);
philosopher(4);
}
philosopher(int i){
while(1){
思考提陶;
p(stick[i]);//取左邊筷子
p(stick[i+1]);//取右邊筷子
進餐;
V(stick[i]);
v(stick[i+1]);
}
}
(四)問題:
如果5個哲學家同時拿起自己左邊的筷子匹层,就會發(fā)生死鎖隙笆。
(五)防止死鎖的方法:
(1)方法一:
規(guī)定在拿到左側(cè)的筷子后,先檢查右面的筷子是否可用升筏。如果不可用撑柔,則先放下左側(cè)筷子, 等一段時間再重復(fù)整個過程您访。
問題:發(fā)生饑餓現(xiàn)象铅忿;
如果同時拿起左邊筷子,則右邊的筷子都不可用灵汪,則放下檀训,然后再次拿起,享言。峻凫。。览露,則誰都無法就餐荧琼,
(2)方法二:
最多允許四個哲學家同時進餐,以保證至少有一個哲學家能夠進餐,最終總會釋
放出他所使用過的兩支筷子,從而可使更多的哲學家進餐。
偽碼:
semaphore chopstick[5]={1差牛,1命锄,1,1多糠,1};
semaphore room=4;
void philosopher(int i)
{
while(true)
{
think();
wait(room); //請求進入房間進餐
wait(chopstick[i]); //請求左手邊的筷子
wait(chopstick[(i+1)%5]); //請求右手邊的筷子
eat();
signal(chopstick[(i+1)%5]); //釋放右手邊的筷子
signal(chopstick[i]); //釋放左手邊的筷子
signal(room); //退出房間釋放信號量room
}
}
(3)將拿左筷子累舷,與拿右筷子當做一個原子操作:(即只有當左右筷子均可以拿到時,才拿筷子夹孔。)
方法一:
利用AND 型信號量機制實現(xiàn):根據(jù)課程講述被盈,在一個原語中析孽,將一段代碼同時需
要的多個臨界資源,要么全部分配給它只怎,要么一個都不分配袜瞬,因此不會出現(xiàn)死鎖的情形。
偽碼:
semaphore chopstick[5]={1身堡,1邓尤,1,1贴谎,1};
void philosopher(int I)
{
while(true)
{
think();
P(chopstick[(I+1)]%5,chopstick[I]);
eat();
V(chopstick[(I+1)]%5,chopstick[I]);
}
}
方法二:
利用信號量的保護機制實現(xiàn)汞扎。通過信號量mutex對eat()之前的取左側(cè)和右側(cè)筷
子的操作進行保護,使之成為一個原子操作擅这,這樣可以防止死鎖的出現(xiàn)澈魄。
偽碼:
semaphore mutex = 1 ;
semaphore chopstick[5]={1,1仲翎,1痹扇,1,1};
void philosopher(int I)
{
while(true)
{
think();
P(mutex);
P(chopstick[(I+1)]%5);
P(chopstick[I]);
V(mutex);
eat();
V(chopstick[(I+1)]%5);
V(chopstick[I]);
}
}
(4)規(guī)定奇數(shù)號的哲學家先拿起他左邊的筷子溯香,然后再去拿他右邊的筷子;而偶數(shù)號 的哲學家則相反鲫构。
偽碼:
semaphore chopstick[5]={1,1玫坛,1结笨,1,1};
void philosopher(int i)
{
while(true)
{
think();
if(i%2 == 0) //偶數(shù)哲學家湿镀,先右后左禀梳。
{
P (chopstick[ i + 1 ] mod 5) ;
P (chopstick[ i]) ;
eat();
V (chopstick[ i + 1 ] mod 5) ;
V (chopstick[ i]) ;
}
Else //奇數(shù)哲學家,先左后右肠骆。
{
p (chopstick[ i]) ;
p (chopstick[ i + 1 ] mod 5) ;
eat();
V (chopstick[ i]) ;
V (chopstick[ i + 1 ] mod 5) ;
}
}