## 問題描述
一張圓桌上坐著5名哲學家,每兩個哲學家之間的桌上擺一根筷子,桌子的中間是一碗米飯,如圖2-10所示。哲學家們傾注畢生精力用于思考和進餐,哲學家在思考時,并不影響他人。只有當哲學家饑餓的時候,才試圖拿起左、 右兩根筷子(一根一根地拿起)。如果筷子已在他人手上,則需等待。饑餓的哲學家只有同時拿到了兩根筷子才可以開始進餐,當進餐完畢后,放下筷子繼續思考。
## 問題分析
1) 關系分析。5名哲學家與左右鄰居對其中間筷子的訪問是互斥關系。
2) 整理思路。顯然這里有五個進程。本題的關鍵是如何讓一個哲學家拿到左右兩個筷子而不造成死鎖或者饑餓現象。那么解決方法有兩個,一個是讓他們同時拿兩個筷子;二是對每個哲學家的動作制定規則,避免饑餓或者死鎖現象的發生。

圖2-10 5名哲學家進餐
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);
}
```
此外還可以釆用AND型信號量機制來解決哲學家進餐問題,有興趣的讀者可以查閱相關資料,自行思考。
- 1. 操作系統概述
- 2.操作系統(計算機)進程和線程管理
- 2.1 進程的概念和特征
- 2.2 進程的狀態與轉換
- 2.3 進程控制
- 2.4 進程的組
- 2.5 進程的通信
- 2.6 線程的概念和多線程模型
- 2.7 處理機調度
- 2.8 操作系統典型調度算法
- 2.9 進程同步的基本概念
- 2.10 實現臨界區互斥的基本方法
- 2.11 信號量
- 2.12 管程:管程的定義、組成及基本特性
- 2.13 經典進程同步問題1
- 2.14 經典進程同步問題2:讀者-寫者問題
- 2.15經典進程同步問題3:哲學家進餐問題
- 2.16 經典進程同步問題4:吸煙者問題
- 2.17 死鎖的概念以及產生死鎖的原因
- 2.18 關于進程和線程的知識點匯總