姓名:李瑶
学号:201821121002
班级:计算1811
1. 哲学家进餐问题
有五个哲学家,他们的生活方式是交替地进行思考和进餐。他们共用一张圆桌,分别坐在五张椅子上。
在圆桌上有五个碗和五支筷子,平时一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕,放下筷子又继续思考。
2. 给出伪代码
5位哲学家与左右邻居对其中间筷子的访问时互斥关系,但与之前遇到的问题不同的是,每个哲学家进程需要同时持有两个临界资源才能开始吃饭,因此要避免临界资源分配不当造成的死锁现象。
通过互斥信号量mutex对eat()之前取左侧和右侧筷子的操作进行保护,可以防止死锁的出现。
semaphore mutex=1;//互斥地取筷子
semaphore chopstick[5]={1,1,1,1,1}
void philosopher (int i){ //i号哲学家的进程
while(true){
think();
wait(cjopstick[i]);
wait(chopstick[(i+1)mod 5]);
signal(mutex);
eat();
signal(chopstick[(i+1)mod 5]);
signal(chopstick[i]);
think();
}
}
3. 给出完整代码
#include<stdio.h> #include<stdlib.h> #include<sys/ipc.h> #include<sys/msg.h> #include<sys/types.h> #include<unistd.h> #include<errno.h> #include<sys/ipc.h> #include<sys/sem.h> #include<sys/wait.h> #define ERR_EXIT(m) \ do { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ }; int semid; #define DELAY (rand() % 5 + 1) void wait_for_2fork(int no) { int left = no; int right = (no + 1) % 5; struct sembuf buf[2] = { {left, -1, 0}, {right, -1, 0} }; semop(semid, buf, 2); } void free_2fork(int no) { int left = no; int right = (no + 1) % 5; struct sembuf buf[2] = { {left, 1, 0}, {right, 1, 0} }; semop(semid, buf, 2); } void philosopere(int no) { srand(getpid()); for (; ;) { printf("%d is thinking\n", no); sleep(DELAY); printf("%d is hungry\n", no); wait_for_2fork(no); printf("%d is eating\n", no); sleep(DELAY); free_2fork(no); } } int main(void) { semid = semget(IPC_PRIVATE, 5, IPC_CREAT | 0666); if (semid == -1) ERR_EXIT("semget"); union semun su; su.val = 1; int i; for (i = 0; i < 5; i++) { semctl(semid, i, SETVAL, su); } int no = 0; pid_t pid; for (i = 1; i < 5; i++) { pid = fork(); if (pid == -1) ERR_EXIT("fork"); if (pid == 0) { no = i; break; } } philosopere(no); return 0; }
4. 运行结果并解释
结果解释:
首先哲学家0~4先进行思考,当饿了的时候就需要就餐,若能同时拿到自己左右两边的叉子则可以开始就餐,否则就需要继续等待。从结果中可以看出五个哲学家最多只能有两个同时就餐,且位置不能相邻;因为结果执行一直没有停止,说明没有发生死锁现象。