问题描述:五名哲学家围坐圆桌,每人需要左右两根筷子才能吃饭。
若每人同时拿起左边筷子,则所有人都在等右边筷子——死锁!
预防策略:限制最多4人同时就餐 · 奇偶规则拿筷子 · 一次拿两根
策略:
就餐中
等待筷子
思考中
死锁!
点击「步进一次」观察哲学家状态变化
哲学家就餐问题 — 三种经典解法代码实现
解法一:限制最多4人同时就餐
Semaphore chopstick[5] = {1,1,1,1,1};
Semaphore limit = 4; // 最多4人同时就餐,打破死锁
void philosopher(int i) {
while(1) {
think(); // 思考
P(limit); // 先申请就餐名额
P(chopstick[i]); // 拿左筷子
P(chopstick[(i+1)%5]); // 拿右筷子
eat(); // 吃饭
V(chopstick[i]); // 放左筷子
V(chopstick[(i+1)%5]); // 放右筷子
V(limit); // 释放就餐名额
}
}
解法二:奇偶规则(打破循环等待)
void philosopher(int i) {
while(1) {
think();
if (i % 2 == 0) { // 偶数号:先左后右
P(chopstick[i]);
P(chopstick[(i+1)%5]);
} else { // 奇数号:先右后左
P(chopstick[(i+1)%5]);
P(chopstick[i]);
}
eat();
V(chopstick[i]);
V(chopstick[(i+1)%5]);
}
}
解法三:一次拿两根筷子(AND信号量)
void philosopher(int i) {
while(1) {
think();
Swait(chopstick[i], chopstick[(i+1)%5]); // 原子操作:同时申请两根
eat();
Ssignal(chopstick[i], chopstick[(i+1)%5]); // 释放两根
}
}