哲学家就餐问题
来源:互联网 发布:帝国cms 栏目绑定信息 编辑:程序博客网 时间:2024/04/29 18:06
哲学家就餐问题。这是由计算机科学家Dijksta提出的经典死锁场景
问题描述:有5个哲学家,这些哲学家只做两件事--思考和吃饭,他们思考的时候不需要任何共享资源,但是吃饭的时候必须使用餐具,而餐具是有限的。原版的故事里,餐具是叉子,吃饭的时候要用两把叉子把面条从碗里捞出来。很显然把叉子换成筷子更合理,所以:一个哲学家需要两根筷子才能吃饭。
现在引入问题:这些哲学家很穷,只买的起5根筷子。他们做成一圈,两个人的中间放一根筷子。哲学家吃饭的时候必须同时得到左边手和右边手的筷子。如果他们身边的任何一位正在使用筷子,那他只有等着。
假设哲学家的编号为A,B,C,D,E,筷子为1,2,3,4,5,哲学家和筷子围成一圈
序号 (哲学家) 左边右边
A 5 1
B 1 2
C 2 3
D 3 4
E 4 5
每个哲学家均为一个单独的线程,每个线程循环左以下动作:思考rand()% 10秒,然后先拿左手边的筷子再拿右边的筷子(筷子这种资源可以用mutex表示),有任何一边拿不到就一直等着,全拿到就吃饭rand()%10秒,然后放下筷子。
编写程序仿真哲学家就餐的场景:
philosopher A fetches chopsticks 5
philosopher B fetches chopsticks 1
...................
要想不产生死锁,只能用trylock,而不能用lock,否则有可能产生阻塞
代码(有点儿繁琐):
#include <stdio.h>#include <stdlib.h>#include <pthread.h>pthread_mutex_t one_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t two_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t three_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t four_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t five_mutex = PTHREAD_MUTEX_INITIALIZER;void think(void){usleep(rand() % 10);}void eat(void){usleep(rand() % 10);}void *thr_fn1(void *arg){while(1){think();//先思考一会儿printf("philosopher A is thinking\n");if(pthread_mutex_trylock(&five_mutex) == 0)//成功获得锁5{printf("Philosopher A fetches chopstick 5\n");if(pthread_mutex_trylock(&one_mutex) != 0)//如果没有获得锁1{pthread_mutex_unlock(&five_mutex);//解锁5printf("Philosopher A releases chopstick 5\n");continue;//接着尝试}//成功获得锁1printf("Philosopher A fetches chopstick 1\n");eat();//成功的话就eatprintf("philosopher A is eating\n");pthread_mutex_unlock(&five_mutex);pthread_mutex_unlock(&one_mutex);printf("Philosopher A releases chopstick 5 -- 1\n");}think();//不成功的话就think}}void *thr_fn2(void *arg){while(1){think();//不成功的话就sleepprintf("philosopher B is thinking\n");if(pthread_mutex_trylock(&one_mutex) == 0)//成功获得锁x{printf("Philosopher B fetches chopstick 1\n");if(pthread_mutex_trylock(&two_mutex) != 0)//如果没有获得锁y{pthread_mutex_unlock(&one_mutex);//解锁xprintf("Philosopher B releases chopstick 1\n");continue;//接着尝试}//成功获得锁yprintf("Philosopher B fetches chopstick 2\n");eat();printf("philosopher B is eating\n");pthread_mutex_unlock(&one_mutex);pthread_mutex_unlock(&two_mutex); printf("Philosopher B releases chopstick 1 -- 2\n");}think();//不成功的话就sleep}}void *thr_fn3(void *arg){while(1){think();//不成功的话就sleepprintf("philosopher C is thinking\n");if(pthread_mutex_trylock(&two_mutex) == 0)//成功获得锁x{printf("Philosopher C fetches chopstick 2\n");if(pthread_mutex_trylock(&three_mutex) != 0)//如果没有获得锁y{pthread_mutex_unlock(&two_mutex);//解锁xprintf("Philosopher C releases chopstick 2\n");continue;//接着尝试}//成功获得锁yprintf("Philosopher C fetches chopstick 3\n");eat();printf("philosopher C is eating\n");pthread_mutex_unlock(&two_mutex);pthread_mutex_unlock(&three_mutex);printf("Philosopher C releases chopstick 2 -- 3\n");}think();//不成功的话就sleep}}void *thr_fn4(void *arg){while(1){ think();//不成功的话就sleep printf("philosopher D is thinking\n");if(pthread_mutex_trylock(&three_mutex) == 0)//成功获得锁x{ printf("Philosopher D fetches chopstick 3\n"); if(pthread_mutex_trylock(&four_mutex) != 0)//如果没有获得锁y {pthread_mutex_unlock(&three_mutex);//解锁xprintf("Philosopher D releases chopstick 3\n");continue;//接着尝试}//成功获得锁yprintf("Philosopher D fetches chopstick 4\n");eat();printf("philosopher D is eating\n");pthread_mutex_unlock(&three_mutex);pthread_mutex_unlock(&four_mutex);printf("Philosopher D releases chopstick 3 -- 4\n");}think();//不成功的话就sleep }}void *thr_fn5(void *arg){while(1){think();//不成功的话就sleepprintf("philosopher E is thinking\n");if(pthread_mutex_trylock(&four_mutex) == 0)//成功获得锁x{printf("Philosopher E fetches chopstick 4\n");if(pthread_mutex_trylock(&five_mutex) != 0)//如果没有获得锁y{pthread_mutex_unlock(&four_mutex);//解锁xprintf("Philosopher E releases chopstick 4\n"); continue;//接着尝试}//成功获得锁yprintf("Philosopher E fetches chopstick 5\n");eat();printf("philosopher E is eating\n");pthread_mutex_unlock(&four_mutex);pthread_mutex_unlock(&five_mutex); printf("Philosopher E releases chopstick 4 -- 5\n");}think();//不成功的话就sleep}}int main(void){pthread_t tid1,tid2,tid3,tid4,tid5;srand((unsigned int)time(NULL));pthread_create(&tid1,NULL,thr_fn1,NULL);pthread_create(&tid2,NULL,thr_fn2,NULL);pthread_create(&tid3,NULL,thr_fn3,NULL); pthread_create(&tid4,NULL,thr_fn4,NULL);pthread_create(&tid5,NULL,thr_fn5,NULL);pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_join(tid3,NULL);pthread_join(tid4,NULL);pthread_join(tid5,NULL);return 0;}
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题 锁
- 哲学家就餐问题
- 哲学家就餐问题
- 关于哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 哲学家就餐问题
- 多线程--哲学家就餐问题
- 原生JavaScript实现弹球游戏
- (使用树结构支持并查集8.4.1)UVA 10608 FRIENDS(查看一个集合中有多少个元素)
- RDF资源描述框架学习笔记
- Euclid's Algorithm 求最大公约数
- 操作系统实验六
- 哲学家就餐问题
- VC中延迟函数执行
- linux 技巧:使用 screen 管理你的远程会话
- 4.21 opendir、readdir和closedir函数-读目录
- 每日一算法:最大公因数、最小公倍数、因式分解
- 任意数字、字符序列,输出它们所有的排列组合
- VS2012 类模块注释
- 使用J2SE API读取Properties文件的六种方法
- c# sqlite 中文乱码