操作系统实验报告:
一.同步:哲学家进餐问题
1.实验名称:
同步:哲学家进餐问题
2.实验目的:
分析进程争用资源的现象,学习解决进程同步与互斥的方法。
3.实验原理:
五位哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,他们的生活方式是交替的进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐,进餐完毕,放下筷子继续思考。若五位哲学家同时拿起左边的筷子,则因五位哲学家均在等待右边的筷子而使他们饥饿而“死”。解决的办法如下:
至多只允许四位哲学家同时去拿左边的筷子;
仅当哲学家左右两边的筷子均可用时才允许他拿起筷子;
规定奇数号哲学家先拿起他左边的筷子,而偶数号哲学家先拿起他右边的筷子。
4.仪器与材料:
PC机,Devc++。
5.实验步骤(代码):
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#define N 5 // 哲学家的数量
sem_t forks[N]; // 信号量数组,表示5个筷子
pthread_t philosophers[N]; // 哲学家线程
sem_t maxDiners; // 最多4个哲学家可以同时进餐
void think(int id) {
printf("哲学家 %d 正在准备\n", id);
sleep(1); // 假设思考1秒钟
}
void eat(int id) {
printf("哲学家 %d 正在吃饭\n", id);
sleep(1); // 假设吃饭1秒钟
}
void *philosopher(void *num) {
long id = (long long) num;
while(1) {
think(id);
sem_wait(&maxDiners); // 获取吃饭许可
sem_wait(&forks[id]); // 先拿起左边的筷子
printf("哲学家 %d 拿起左边的筷子 %d\n", id, id);
sem_wait(&forks[(id+1)%N]); // 再拿起右边的筷子
printf("哲学家 %d 拿起右边的筷子 %d\n", id, (id+1)%N);
eat(id);
sem_post(&forks[id]); // 放下左边的筷子
printf("哲学家 %d 放下左边的筷子 %d\n", id, id);
sem_post(&forks[(id+1)%N]); // 放下右边的筷子
printf("哲学家 %d 放下右边的筷子 %d\n", id, (id+1)%N);
sem_post(&maxDiners); // 释放吃饭许可
}
}
int main() {
sem_init(&maxDiners, 0, 4); // 初始化maxDiners信号量为4,表示最多有4个哲学家可以同时吃饭
int i;
for( i = 0; i < N; i++) {
sem_init(&forks[i], 0, 1); // 初始化每个信号量为1,表示每个筷子都可用
}
for( i = 0; i < N; i++) {
pthread_create(&philosophers[i], NULL, philosopher, (void*)(long long)i); // 创建哲学家线程
}
for( i = 0; i < N; i++) {
pthread_join(philosophers[i], NULL); // 等待所有哲学家线程结束
}
return 0;
}
6.问题即讨论
亦可选择读者-写者、单行轨道、病人就诊、公交车行驶、超市购物、理发师理发等其他问题作为设计对象。