回顾一下死锁成立需要 四个条件同时满足:
互斥条件:资源不可共享
占有且等待:进程已经持有至少一个资源,同时请求新的资源
不可剥夺:已分配资源不能被抢走
循环等待:存在一个环,每个进程都在等待下一个持有的资源
一、核心思路
-
每根筷子对应一个互斥信号量 chopstick[i]
-
限制同时就餐人数 ≤ N-1(破坏占有且等待条件,避免死锁)
-
每个哲学家:
- 先思考
- 尝试拿左右筷子
- 吃完释放筷子
二、C 语言伪代码实现
c
#include <semaphore.h>
#include <pthread.h>
#define N 5 // 哲学家数量
sem_t chopstick[N]; // 每根筷子
sem_t room; // 限制同时就餐人数
void* philosopher(void* num) {
int i = *(int*)num;
while (1) {
// 思考
think(i);
// 进入餐厅,限制最多 N-1 哲学家同时尝试拿筷子
sem_wait(&room);
// 拿筷子
sem_wait(&chopstick[i]); // 左筷子
sem_wait(&chopstick[(i+1)%N]); // 右筷子
// 吃饭
eat(i);
// 放筷子
sem_post(&chopstick[i]);
sem_post(&chopstick[(i+1)%N]);
// 离开餐厅
sem_post(&room);
}
}
为什么破坏了"占有且等待"
N 个哲学家最多 N-1 人同时尝试拿筷子
这样:
至少有一个哲学家能拿到 两根筷子并吃饭
吃完释放 → 其他哲学家可以继续拿
关键:哲学家不会永远占着一根筷子等待另一根
→ 占有且等待条件被破坏 → 系统无法形成死锁
理解口诀
"限制人数,拿筷子互斥 → 吃完放回 → 死锁破"