問題描述
五個哲學家共用一張圓桌,分別坐在五張椅子上,圓桌上有五個碗和五只筷子。平時哲學家進行思考,當即飢餓時拿起左右兩邊的筷子,只有拿到兩只筷子時才能進餐,進餐完畢,放下筷子繼續思考。
問題分析
這是經典的進程同步問題。筷子是臨界資源,每只筷子都用一個互斥量表示。
semaphore chopstick[5] = {1, 1, 1, 1, 1}
錯誤示例:
semaphore chopstick[5] = {1, 1, 1, 1, 1};
void philosopher(int i){
do{
wait(chopstick[i]);
wait(chopstick[(i+1)%5]);
//eat
//...
signal(chopstick[i]);
signal(chopstick[(i+1)%5]);
//think
//...
}while(true);
}
這樣做會帶來一個問題,當五個哲學家同時飢餓拿起左邊的筷子時,試圖拿右邊的筷子,就會進入死鎖。
解決方法
1.至多有四位哲學家同時拿起左邊的筷子,即至多只有四個哲學家同時進餐,這樣能保證至少有一個哲學家能夠進餐。
2.僅當哲學家左右兩邊的筷子都可用時,才能進餐
3.規定奇數號哲學家先拿左邊的筷子,再拿右邊的筷子;偶數號哲學家相反。
解法1
用一個信號量counter
表示哲學家同時進餐的人數,初始值為4
semaphore chopstick[5] = {1, 1, 1, 1, 1};
counter=4;
void philosopher(int i){
do{
wait(counter);
wait(chopstick[i]);
wait(chopstick[(i+1)%5]);
//eat
//...
signal(chopstick[i]);
signal(chopstick[(i+1)%5]);
signal(counter)
//think
//...
}while(true);
}
解法2
使用AND型信號量,當兩個臨界資源都滿足后才能進餐
semaphore chopstick[5] = {1, 1, 1, 1, 1};
void philosopher(int i){
do{
Swait(chopstick[i], chopstick[(i+1)%5]);
//eat
//...
Ssignal(chopstick[i], chopstick[(i+1)%5]);
//think
//...
}while(true);
}
解法3
semaphore chopstick[5] = {1, 1, 1, 1, 1};
void philosopher(int i){
do{
if(i%2){
wait(chopstick[i]);
wait(chopstick[(i+1)%5]);
}
else{
wait(chopstick[(i+1)%5]);
wait(chopstick[i]);
}
//eat
//...
signal(chopstick[i]);
signal(chopstick[(i+1)%5]);
//think
//...
}while(true);
}