1. 引言
問題描述: 5個哲學家圍坐在一個圓桌上,每兩個哲學家之間都有一只筷子,哲學家平時進行思考,只有當他們飢餓時,才拿起筷子吃飯。規定每個哲學家只能先取其左邊筷子,然后取其右邊筷子,然后才可以吃飯。
2. 求解方法
-
信號量設置。定義互斥信號量數組chopstick[5] = {1, 1, 1, 1, 1}, 用於對5個筷子的互斥訪問。
對哲學家按順序從0~4編號,哲學家i左邊的筷子編號為i, 哲學家右邊的筷子編號為(i+1)%5.
//定義信號量數組chopstick[5],並初始化i號哲學家的進程 semaphore chopstick[5] = {1,1,1,1,1}; Pi() { do { P(chopstick[i]); //取左邊筷子 P(chopstick[(i+1)%5]); //取右邊筷子 eat; //進餐 V(chopstick[i]); //放回左邊筷子 V(chopstick[(i+1)%5]); //放回右邊筷子 think; //思考 } while (1); }
-
為了防止死鎖的發生,可以對哲學家進程施加一些限制條件,比如至多允許四個哲學家同時進餐;僅當一個哲學家左右兩邊的筷子都可用時才允許他抓起筷子; 對哲學家順序編號, 要求奇數號的哲學家先抓起左邊的筷子,然后再轉他右邊的筷子, 而偶數號哲學家則剛好相反。
正解指定規則如下: 假設采用第二種方法, 當一個哲學家左右兩邊的筷子都可以用時, 才允許他抓起筷子。
//初始化信號量 semaphore chopstick[5] = {1,1,1,1,1}; semaphore mutex = 1; //設置取筷子的信號量 Pi() { //i號哲學家的進程 do { P(mutex); //在取筷子前獲得互斥量 P(chopstick[i]); //取左邊筷子 P(chopstick[(i+1)%5]); //取右邊筷子 V(mutex); //釋放取筷子的信號量 eat; //進餐 V(chopstick[i]); //放回左邊筷子 V(chopstick[(i+1)%5]); //放回右邊筷子 think; //思考 } while(1); }
3. 結語
-
哲學家進餐問題的思維精髓是: 考慮能不能一次拿起兩只筷子才做決定的話,就會避免死鎖問題.