哲学家就餐问题是经典的进程同步问题,而以下解决思路也堪称经典。
n 哲学家进餐问题
n 解决思路1:只允许4位哲学家同时拿筷子。此时必然有一个哲学家能拿到2根筷子。
n 如何保证只有4位哲学家同时拿筷子?
n 可以设置一个初值为4的资源信号量。比如,4张椅子,哲学家进餐之前必须先拿到椅子才能做到桌前拿筷子。进餐完毕后,不但要释放筷子,还要释放椅子。
n 哲学家进餐问题
n 解决思路1:只允许4位哲学家同时拿筷子。此时必然有一个哲学家能拿到2根筷子。
n var chopstick: array[0…4] of semaphore :=(1,1,1,1,1);
n chair: semaphore := 4;
n philosopher(i): begin
n repeat
n think;
n wait(chair); //拿椅子
n wait(chopstick[i]);
n wait(chopstick[(i+1) mod 5]);
n eat;
n signal(chopstick[i]);
n signal(chopstick[(i+1) mod 5]);
n signal(chair);//释放椅子
n until false;
n end
n 哲学家进餐问题:解决思路1
n 椅子这种资源信号量可以减少个数。极端的情况是chair初值为1,即只有一把椅子,那么每次只允许一个哲学家进餐,肯定不会饿死,但是效率低。
n 哲学家进餐问题:
n 解决思路2:只有哲学家同时能够拿起左右两边的筷子的时候,才允许拿筷子。
n 此思路最简单的办法是用AND信号量解决。不过本次我们考虑用记录型信号量解决的办法。
n 关键词:原子操作。我们想办法使得哲学家拿左边和右边筷子的过程变得不受打扰。
n 哲学家进餐问题:解决思路2
n 如何让拿两边筷子的动作变成一个原子操作?
n 桌边配备一名服务员,饥饿时招呼一个服务员过来帮哲学家拿筷子。服务员拿完左右两边的筷子就可以去帮助其他人服务。
n 哲学家进餐问题
n 解决思路2:只有哲学家同时能够拿起左右两边的筷子的时候,才允许拿筷子。
n var chopstick: array[0…4] of semaphore :=(1,1,1,1,1);
n mutex := 1;
n philosopher(i): begin
n repeat
n think;
n wait(mutex); //招呼服务员过来
n wait(chopstick[i]);
n wait(chopstick[(i+1) mod 5]);
n signal(mutex);//服务员拿完筷子可以给其他人服务
n eat;
n signal(chopstick[i]);
n signal(chopstick[(i+1) mod 5]);
n until false;
n end
n 哲学家进餐问题:解决思路2
如果释放服务员的操作在释放筷子之后进行,而不是在吃饭前进行,则演变成了竞争椅子的极端情况(1把椅子)
n 哲学家进餐问题:解决思路2
n 这种方法的问题:假设0号哲学家正在用餐,此时1号和2号哲学家饥饿了,两者同时招呼服务员。最终服务员为1号服务,但因被0号哲学家占用的1号筷子未释放,因此1号哲学家无法就餐,但他也没有释放服务员。本来2号哲学家有机会吃饭的,但因为没有招呼到服务员,因此必须等待。
n 哲学家进餐问题:解决思路2
n 解决该问题的方法:服务员只有在确认左右两边哲学家都没就餐时才会帮该哲学家拿筷子,否则该哲学家释放服务员。
下面用类C实现这种方法,在该方法中,不使用筷子信号量,而是为每个哲学家设置一个状态位,该状态位可以为THINKING或EATING状态。状态位必须被互斥访问。
#define N 5 //哲学家数
#define LEFT (i+N-1) % N //第i个哲学家左邻居编号
#define RIGHT (i+1) % N //右邻居编号
#define THINKING 0 //思考状态
#define EATING 1 //吃饭状态
int state[N]; // 定义哲学家状态,初始值为0,即思考状态
semaphore mutex =1; //状态位的互斥信号量
void philosopher(int i){
while(true){
think();
take_chop(i);//拿两支筷子
eat();
put_chop(i);//放下两支筷子
}
}
void take_chop(int i){
wait(mutex);//进入临界区
if((state[LEFT]!=EATING) && (state[RIGHT]!= EATING)){
state[i]=EATING;//如果左右两边哲学家都没吃饭,则i可吃饭
}
signal(mutex);
}
void put_chop(int i){
wait(mutex);
state[i] = THINKING;//吃完饭释放筷子
signal(mutex);
}
n 哲学家进餐问题:
n 解决思路3:奇数号哲学家先拿左边筷子,偶数号哲学家先拿右边筷子。(或者相反)
n 此时五位哲学家总是先竞争奇数号筷子,获得后再竞争偶数号筷子。
n var chopstick: array[0…4] of semaphore :=(1,1,1,1,1);
n philosopher(i): begin
n repeat
n think;
n wait(chopstick[(i+(i+1) mod 2) mod 5]);
n wait(chopstick[(i+(i mod 2)) mod 5]);
n eat;
n signal(chopstick[(i+(i+1) mod 2) mod 5]);
n signal(chopstick[(i+(i mod 2)) mod 5]);
n until false;
n end
n 哲学家进餐问题:解决思路3
n 思路3的一些变种:
n 任意一位哲学家与其他哲学家反方向申请筷子
先拿筷子的三位哲学家与后面两位哲学家反方向申请筷子。
相关推荐
文档为实验报告,运行环境是ubantu,文档包含哲学家就餐问题的代码,使用三种方法解决哲学家就餐问题,顺序资源法,加房间法和P_sim法,希望对大家有帮助
java编写的哲学家就餐问题的解决方案,有图形界面,我是重庆大学的。如果你也是重庆大学的,那就请毫不犹豫的下载吧,肯定是你需要的代码,信号量
java解哲学家就餐问题 哲学家进餐问题是一个多线程运用的经典例子,涉及到线程同步/互斥,临界区访问问题以及一个避免死锁的解决方法。 有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,...
经典的哲学家就餐问题,这里是6个哲学家就餐,用p,v原语实现避免死锁,linux下运行
这是一个描叙哲学家进餐问题的代码。。。。。。C语言写额
分析哲学家进餐问题,p,v操作实现互斥与同步,分析记录性信号量的不足,并指出给改进方法 方法一:最多允许4人同时进餐; 方法二:分奇偶数进餐,以及AND型信号量解决该问题。 (免费下载,无需积分)
哲学家进餐问题
有三个.cpp文件,代码是我亲手写的,都可以运行,这个代码包含有3种方式避免死锁的方法,一个是允许四个哲学家同时进餐,第二个是一下子就拿两根筷子,否则不拿,第三个就是奇数哲学家先拿左边的筷子,偶数哲学家拿...
操作系统初学,关于信号量同步的实验报告,用三种方法避免哲学家进餐问题死锁,a:and信号量,b:控制进餐人数,c设置条件
哲学家就餐问题的分析与代码,供大家参考吧,很详细
关于5个哲学家就餐线程同步问题的解决方法 此方法对左右手刀叉实行控制,防止了死锁,实现了线程的同步 注意5个以上的哲学家亦可用此方法解决
有五个哲学家,他们的生活方式是交替地进行思考和进餐。他们共用一张圆桌,分别坐在五张椅子上。 在圆桌上有五个碗和五把叉子,平时...哲学家进餐问题可看作是并发进程并发执行时处理共享资源的一个有代表性的问题。
使用了C#对哲学家就餐问题进行了仿真,采用进程交互法,并使用批均值法、重复删除法对仿真数据进行了分析
死锁是进程并发执行过程中可能出现的现象,哲学家就餐问题是描述死锁的经典例子。假设有几位哲学家围坐在一张餐桌旁,桌上有吃不尽的食品,每两位哲学家之间摆放着一根筷子,筷子的个数与哲学家的数量相等,每一位...
用c++实现哲学家进餐问题 哲学家i思考中 1 输入饥饿哲学家 2 停止就餐 3 显示个哲学家的状态 "饥饿哲学家的数目 各饥饿哲学家的编号 输入释放筷子的哲学家编号
有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃通心粉.为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从...
JAVA实现哲学家就餐问题