問題描述
一張圓桌上坐着5名哲學家,每兩個哲學家之間的桌上擺一根筷子,桌子的中間是一碗米飯,如圖2-10所示。哲學家們傾注畢生精力用於思考和進餐,哲學家在思考時,並不影響他人。只有當哲學家飢餓的時候,才試圖拿起左、 右兩根筷子(一根一根地拿起)。如果筷子已在他人手上,則需等待。飢餓的哲學家只有同時拿到了兩根筷子才可以開始進餐,當進餐完畢后,放下筷子繼續思考。
問題分析
1) 關系分析。5名哲學家與左右鄰居對其中間筷子的訪問是互斥關系。
2) 整理思路。顯然這里有五個進程。本題的關鍵是如何讓一個哲學家拿到左右兩個筷子而不造成死鎖或者飢餓現象。那么解決方法有兩個,一個是讓他們同時拿兩個筷子;二是對每個哲學家的動作制定規則,避免飢餓或者死鎖現象的發生。
3) 信號量設置。定義互斥信號量數組Ch0PstiCk[5] = {l, 1, 1, 1, 1}用於對5個筷子的互斥訪問。
對哲學家按順序從0~4編號,哲學家i左邊的筷子的編號為i,哲學家右邊的筷子的編號為(i+l)%5。
semaphore chopstick[5] = {1,1,1,1,1}; //定義信號量數組chopstick[5],並初始化 Pi(){ //i號哲學家的進程 do{ P (chopstick[i] ) ; //取左邊筷子 P (chopstick[(i+1) %5] ) ; //取右邊篌子 eat; //進餐 V(chopstick[i]) ; //放回左邊筷子 V(chopstick[(i+l)%5]); //放回右邊筷子 think; //思考 } while (1); }
該算法存在以下問題:當五個哲學家都想要進餐,分別拿起他們左邊筷子的時候(都恰好執行完wait(chopstick[i]);)筷子已經被拿光了,等到他們再想拿右邊的筷子的時候(執行 wait(chopstick[(i+l)%5]);)就全被阻塞了,這就出現了死鎖。
預防死鎖,可以對哲學家進程施加一些限制條件,比如至多允許四個哲學家同時進餐;僅當一個哲學家左右兩邊的筷子都可用時才允許他抓起筷子;對哲學家順序編號,要求奇數號哲學家先抓左邊的筷子,然后再轉他右邊的筷子,而偶數號哲學家剛好相反。正解制定規則如下:假設釆用第二種方法,當一個哲學家左右兩邊的筷子都可用時,才允許他抓起筷子。
semaphore chopstick[5] = {1,1,1,1,1}; //初始化信號量 semaphore mutex=l; //設置取筷子的信號量 Pi(){ //i號哲學家的進程 do{ P (mutex) ; //在取筷子前獲得互斥量,一次只能由一個哲學家取筷子 P (chopstick [i]) ; //取左邊筷子 P (chopstick[ (i+1) %5]) ; //取右邊筷子 V (mutex) ; //釋放取筷子的信號量 eat; //進餐 V(chopstick[i] ) ; //放回左邊筷子 V(chopstick[ (i+l)%5]) ; //放回右邊筷子 think; // 思考 }while(1); }