如何在哲学家就餐问题代码中触发死锁状态?
如何修改哲学家就餐问题代码以产生死锁
你的原代码采用了Dijkstra的防死锁解法,通过verifica函数全局检查左右邻居的就餐状态,确保只有当两边都没人吃饭时,当前哲学家才能拿起叉子,从根源上避免了“每人持一根叉子等待另一根”的死锁场景。要制造死锁,我们需要去掉这个全局协调逻辑,让每个哲学家独立地按固定顺序拿叉子,最终形成循环等待。
核心修改思路
把每个叉子设为独立的信号量,让所有哲学家都遵循先拿左侧叉子,再拿右侧叉子的顺序。当所有哲学家同时拿起左侧叉子后,都会卡在等待右侧叉子的状态——此时每个叉子都被一人持有,没人能释放手里的叉子,死锁就会产生。
修改后的完整代码
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <semaphore.h> #include <stdbool.h> #define NUM_FIL 5 #define PENSA 2 #define AFFAMATO 1 #define MANGIA 0 #define SINISTRA (filosofi + 4) % NUM_FIL #define DESTRA (filosofi + 1) % NUM_FIL int stato[NUM_FIL]; int fil[NUM_FIL] = {0,1,2,3,4}; sem_t mutex; sem_t forchette[NUM_FIL]; // 每个叉子对应一个信号量,初始值为1表示可用 void schermoIniziale(); void prendeForchetta(int filosofi); void lasciaForchetta(int filosofi); void* filosofo(void* num); void prendeForchetta(int filosofi){ sem_wait(&mutex); stato[filosofi] = AFFAMATO; printf("Filosofo %d e' affamato\n", filosofi + 1); sem_post(&mutex); // 固定顺序:先拿自己面前的叉子(左侧),再拿右侧邻居的叉子 sem_wait(&forchette[filosofi]); printf("Filosofo %d prende la forchetta %d\n", filosofi + 1, filosofi + 1); sem_wait(&forchette[DESTRA]); printf("Filosofo %d prende la forchetta %d\n", filosofi + 1, DESTRA + 1); sem_wait(&mutex); stato[filosofi] = MANGIA; printf("Filosofo %d MANGIA\n", filosofi + 1); sem_post(&mutex); sleep(1); } void lasciaForchetta(int filosofi){ sem_wait(&mutex); stato[filosofi] = PENSA; printf("Filosofo %d lascia le forchette %d e %d \n", filosofi + 1, filosofi + 1, DESTRA + 1); printf("Filosofo %d PENSA\n", filosofi + 1); sem_post(&mutex); // 释放叉子,顺序不影响死锁产生,只需和拿起顺序对应 sem_post(&forchette[filosofi]); sem_post(&forchette[DESTRA]); sleep(1); } void* filosofo(void* num){ while (true) { int* i = num; sleep(1); prendeForchetta(*i); sleep(1); lasciaForchetta(*i); } } int main(){ int i; pthread_t fil_id[NUM_FIL]; sem_init(&mutex, 0, 1); schermoIniziale(); sleep(2); // 初始化每个叉子信号量,初始值为1(可用状态) for (i = 0; i < NUM_FIL; i++){ sem_init(&forchette[i], 0, 1); } for (i = 0; i < NUM_FIL; i++) { pthread_create(&fil_id[i], NULL, filosofo, &fil[i]); printf("Filosofo %d PENSA\n", i + 1); } for (i = 0; i < NUM_FIL; i++){ pthread_join(fil_id[i], NULL); } } void schermoIniziale(){ printf("+-----------BENVENUTO------------+\n"); printf("| Dining philosophers problem |\n"); printf("+--------------------------------+\n\n"); }
死锁产生过程说明
程序运行后,所有哲学家会在思考结束后尝试拿起左侧叉子。由于操作系统的调度特性,很容易出现所有哲学家都成功拿起左侧叉子的情况:此时每个叉子都被一个哲学家持有,而每个哲学家都在等待右侧邻居手里的叉子。没有任何哲学家能继续执行(拿不到第二根叉子就无法吃饭),也不会有人释放手里的叉子(只有吃完才会释放),最终形成循环等待,触发死锁。
内容的提问来源于stack exchange,提问作者Francesco Nardiello
相关产品推荐
相关产品推荐

