原版的故事里有五个哲学家(不过我们写的程序可以有N个哲学家),这些哲学家们只做两件事--思考和吃饭,他们思考的时候不需要任何共享资源,但是吃饭的时候就必须使用餐具,而餐桌上的餐具是有限的,原版的故事里,餐具是叉子,吃饭的时候要用两把叉子把面条从碗里捞出来。很显然把叉子换成筷子会更合理,所以:一个哲学家需要两根筷子才能吃饭。
现在引入问题的关键:这些哲学家很穷,只买得起五根筷子。他们坐成一圈,两个人的中间放一根筷子。哲学家吃饭的时候必须同时得到左手边和右手边的筷子。如果他身边的任何一位正在使用筷子,那他只有等着。
假设哲学家的编号是A、B、C、D、E,筷子编号是1、2、3、4、5,哲学家和筷子围成一圈如下图所示:
解法:
至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。将room作为信号量,只允许4个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入餐厅的哲学家进入room的等待队列
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<process.h>
#include<windows.h>
int ROOM=4;
int chopstick[5]={1,1,1,1,1};
void return_chopstick(int i){
chopstick[i]=1;
}
void take_chopstick(int i){
while(1){
if(chopstick[i]!=0){
chopstick[i]=0;
break;
}else{
Sleep(200);
}
}
}
void think(int i){
int num;
srand((int)time(NULL));
num=rand()/50+1;
printf("哲学家%d 正在思考......\n\n",i);
Sleep(10*num);
printf("哲学家%d 思考完毕......\n\n",i);
}
void eat(int i){
int num;
srand((int)time(NULL));
num=rand()/50+1;
ROOM-=1;
while(1){
if(ROOM!=0){
take_chopstick(i-1);
take_chopstick(i%5);
printf("哲学家%d 正在吃饭中......\n\n",i);
Sleep(10*num);
printf("哲学家%d 吃饭完毕......\n\n",i);
return_chopstick(i-1);
return_chopstick(i%5);
ROOM+=1;
break;
}else{
printf("哲学家%d等待中......\n\n",i);
Sleep(200);
}
}
}
void philosopher1(void *p) {
while(1){
think(1);
eat(1);
}
}
void philosopher2(void *p) {
while(1){
think(2);
eat(2);
}
}
void philosopher3(void *p) {
while(1){
think(3);
eat(3);
}
}
void philosopher4(void *p) {
while(1){
think(4);
eat(4);
}
}
void philosopher5(void *p) {
while(1){
think(5);
eat(5);
}
}
int main(){
int n;
printf(" 哲学家就餐模拟系统 \n\n");
printf("#######################################\n");
printf("# #\n");
printf("# #\n");
printf("# 1、开始模拟 #\n");
printf("# #\n");
printf("# #\n");
printf("# 2、退出系统 #\n");
printf("# #\n");
printf("# #\n");
printf("# #\n");
printf("#######################################\n");
scanf("%d",&n);
if(n==1){
_beginthread(philosopher1, 0, NULL);
_beginthread(philosopher2, 0, NULL);
_beginthread(philosopher3, 0, NULL);
_beginthread(philosopher4, 0, NULL);
_beginthread(philosopher5, 0, NULL);
_endthread();
_endthread();
_endthread();
_endthread();
_endthread();
}else{
exit(0);
}
return 0;
}