哲学家就餐问题
6个哲学家进餐问题预防死锁
红河学院课程设计报告操作系统课程名称:6个哲学家进餐设计题目:院系:工学院专业:计算机科学与技术班级:11计科班曹永前设计者:学号:201101030466指导教师:韦相2013 年 5 月26 日1. 问题描述:一个房间内有6个哲学家,他们的生活就是思考和进食。
哲学家思考后,过一定的时间就会饥饿,饥饿之后就想吃饭,吃饭后再思考。
房间里有一张圆桌,桌子周围放有五把椅子,分别属于五位哲学家每两位哲学家之间有一把叉子,哲学家进食时必须同时使用左右两把叉子。
2. 问题分析1、写出哲学家进餐的算法描述。
用六只筷子解决需要用两双筷子来进餐的六个哲学家,由于每个哲学家都需要其周围的两只筷子,所以筷子是公用信号量,这久需要设置一个互斥信号量,来使六个哲学家互斥的进餐.具体做法将六个信号量设置为0-5,用pv 源于来控制信号量,并将六个哲学家分别编号为0-5.经过仔细分析我们会发现,有这样一个问题存在,就是当每个哲学家都申请到他周围的一只筷子时,由于他们每人都只有一只筷子无法进餐,没有进餐他们就无法释放他们已经得得到的筷子,这样是进餐出于一种僵局,无法继续下去,这就是死锁问题.2、死锁问题的分析与具体的解决方法。
死锁问题就是当每个哲学家都拿到且只拿到一只筷子,这样每个哲学家都无法进餐,也无法释放所得到的筷子,所以解决死锁我们就要从这入手,就是怎样去预防使所有哲学家不要同时去申请他们同一方向的筷子.根据这解决死锁的方法有以下几种:a.每一次最多只能有五个哲学家申请进餐.这样其中的一个哲学家就能申请到两只筷子,就能够进餐,再将筷子释放给其他哲学家进餐.b.用AND信号量,就是哲学家需同时申请其左右两边的筷子,两边都有资源的时候,才能让这个哲学家得到资源,这样哲学家只要申请到筷子就能进餐, 再将筷子释放给其他哲学家进餐.c.用管程机制来实现。
d.我们前面已经将每个哲学家都分配了一个编号,我们可以编号为奇数的哲学家首先去申请其左边的筷子,再去申请其右手边的筷子;让编号为偶数的哲学家,先去申请其右边的筷子,再去申请其左边的筷子.我们可以看出编号为奇数的哲学家左边,与编号为偶数的哲学家的右边为同一只筷子,当其中一个哲学家拿到此筷子后,他另一边的筷子也是空闲的,这样就能避免死锁.主程序中我使用的是最后一种避免死锁的方法.3、用C程序实现哲学家进餐。
哲学家就餐问题与银行家算法
问题解决
方法一
第一种解决死锁问题的办法就是同时只允许四位哲学家同时拿起同一 边的筷子,这样就能保证一定会有一位哲学家能够拿起两根筷子完成 进食并释放资源,供其他哲学家使用,从而实现永动,避免了死锁。 举个最简单的栗子,假定0~3号哲学家已经拿起了他左边的筷子,然后 当4号哲学家企图去拿他左边的筷子的时候,将该哲学家的线程锁住, 使其拿不到其左边的筷子,然后其左边的筷子就可以被3号哲学家拿到, 然后3号哲学家进餐,释放筷子,然后更多的哲学家拿到筷子并进餐。 如何才能实现当4号哲学家企图拿起其左边的筷子的时候将该哲学家 的线程阻塞?这个时候就要用到该问题的提出者迪杰斯特拉(这货还 提出了迪杰斯特拉最短路径算法,著名的银行家算法也是他发明的) 提出的信号量机制。因为同时只允许有四位哲学家同时拿起左筷子, 因此我们可以设置一个信号量r,使其初始值为4,然后每当一位哲学 家企图去拿起他左边的筷子的时候,先对信号量做一次P操作,从而当 第五位哲学家企图去拿做筷子的时候,对r做一次P操作,r = -1,由r < 0得第五位哲学家的线程被阻塞,从而不能拿起左筷子,因此也就避免 了死锁问题。然后当哲学家放下他左边的筷子的时候,就对r做一次V 操作。
死锁,但是处于不安全状态
哲学家进餐问题的趣味例子
哲学家进餐问题的趣味例子
哲学家进餐问题是一个经典的计算机科学问题,用来展示并发编程中可能出现
的资源竞争和死锁问题。
这个问题的描述是:五位哲学家围坐在一张圆桌前,每位哲学家面前有一碗意面,但他们之间共享一把只能被一个人同时使用的餐叉。
每位哲学家需要先拿起右手边的餐叉,再拿起左手边的餐叉才能吃饭,吃完后放下餐叉继续思考问题。
如果哲学家之间同时试图拿起自己左右手边的餐叉,就会导致死锁问题,无法继续进餐。
这个问题的趣味例子在于通过这种抽象的场景,展现了并发编程中常见的竞争
和死锁问题。
实际上,哲学家进餐问题也可以被看作是对资源管理和同步机制的一种考验。
如果每位哲学家都按照固定的顺序拿餐叉,就不会发生死锁;而如果哲学家们都随机地尝试拿餐叉,就可能会出现资源竞争的问题,导致无法进餐。
这个问题的趣味之处在于,通过一个简单的场景,展示了复杂的并发编程中可
能出现的问题,让人们更加深入地理解并发编程中的挑战和技巧。
通过哲学家进餐问题的讨论,人们可以思考如何设计合理的同步机制和资源管理策略,避免竞争和死锁问题的发生,提高程序的并发性能和稳定性。
总的来说,哲学家进餐问题是一个充满趣味和启发的例子,能够帮助人们更好
地理解并发编程中的难点,同时也能够激发人们对于解决问题的创造力和思考能力。
通过这个例子的讨论,人们可以不仅仅学到技术知识,更能够培养出解决问题的能力和思维方式,为未来的学习和工作打下坚实的基础。
愿每位哲学家都能够顺利进餐,思考问题,探索未知的世界。
五个哲学家吃饭问题详细解答
五个哲学家吃饭问题详细解答在一个阳光明媚的下午,五个哲学家聚在一起,准备享用一顿丰盛的午餐。
听起来很简单吧?但实际上,这顿饭可没那么容易!让我们来看看这群头脑发达的哲学家是如何在吃饭问题上纠结的。
1. 场景设定1.1 哲学家的基本设定这五位哲学家,一个比一个聪明。
他们分别是苏格拉底、柏拉图、康德、尼采和海德格尔。
你可以想象,他们脑袋里装的全是复杂的哲学思想,而不是食物的搭配。
所以,当这五位坐下来,面对一桌子美味的食物时,事情就开始变得有趣了。
1.2 吃饭的挑战问题来了:他们每个人都必须遵守一个规则——不可以同时吃饭,得轮流。
你想想,五个哲学家加上一个轮流吃饭的规则,这可真是“见鬼了”的挑战!想要吃上一口美味的菜,简直比推理一个哲学命题还难。
他们轮流吃饭的原则,真是把这顿饭变成了一场智力的较量。
2. 各自的哲学观2.1 苏格拉底的理性苏格拉底首先站出来,他一边抚摸着自己的胡须,一边说:“吃饭嘛,首先得用理性来解决问题。
”他鼓励大家先讨论,谁应该先吃,谁应该后吃。
他认为,只有通过理性对话,才能达到最佳的吃饭方案。
可是,你能想象吗?这一讨论持续了整整一个小时,食物都快冷掉了!2.2 柏拉图的理想接着柏拉图出场,他满脸严肃地说:“我们要追求理想的吃饭方式。
”他想出了一个绝妙的主意:每个人都应该依照自己的德性来决定吃的顺序。
结果,大家一顿争论,谁的德性更高?苏格拉底说他是智者,康德坚持说自己是道德之父,而尼采则跳出来,吼着“超人才能吃超好的饭!”搞得大家乱成一团,吃的机会又飞了。
3. 饥饿的对抗3.1 食物的诱惑这时,桌子上的食物开始散发出诱人的香气,真是令人垂涎欲滴。
五位哲学家每个人的肚子都开始抗议,仿佛在唱着“我们要吃饭”的歌。
吃饭这件事,从理性讨论变成了一场生存竞争。
每个人都在默默地想着:“快点!要是再不吃,我的哲学思想就要被饿死了!”3.2 轮流的尴尬最终,他们决定采取轮流吃饭的方式。
可当轮到康德的时候,他又开始喋喋不休,讲起了“绝对命令”的哲学,让其他人都想打瞌睡。
哲学家进餐问题
哲学家进餐问题1.问题描述:哲学家进餐问题描述有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。
约束条件(1)只有拿到两只筷子时,哲学家才能吃饭。
(2)如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。
(3)任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子。
2.求解方法(1).信号量的设置放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥访问,可以用一个信号量表示筷子,由这五个信号量构成信号量数组。
semaphore chopstick[5] = {1,1,1,1,1};while(true){/*当哲学家饥饿时,总是先拿左边的筷子,再拿右边的筷子*/wait(chopstick[i]);wait(chopstick[(i+1)%5]);// 吃饭/*当哲学家进餐完成后,总是先放下左边的筷子,再放下右边的筷子*/signal(chopstick[i]);signal(chopstick[(i+1)%5]);}上述的代码可以保证不会有两个相邻的哲学家同时进餐,但却可能引起死锁的情况。
假如五位哲学家同时饥饿而都拿起的左边的筷子,就会使五个信号量chopstick都为0,当他们试图去拿右手边的筷子时,都将无筷子而陷入无限期的等待。
(2)避免死锁策略一原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。
定义信号量count,只允许4个哲学家同时进餐,这样就能保证至少有一个哲学家可以就餐。
semaphore chopstick[5]={1,1,1,1,1};semaphore count=4; // 设置一个count,最多有四个哲学家可以进来void philosopher(int i){while(true){think();wait(count); //请求进入房间进餐 当count为0时 不能允许哲学家再进来了wait(chopstick[i]); //请求左手边的筷子wait(chopstick[(i+1)%5]); //请求右手边的筷子eat();signal(chopstick[i]); //释放左手边的筷子signal(chopstick[(i+1)%5]); //释放右手边的筷子signal(count); //退出房间释放信号量}}策略二原理:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。
哲学家用餐问题
哲学家一(线程一函数)
读懂整 个程序。 请写出其余两个线程 的函数Thread2Proc 和 Thread3Proc ,使他们 都先取右边的筷子, 后取左边的筷子。执 行,写出实验结果或 现象。回答问题(3)
(2)描述一个既没有两座同时吃饭,又没有人饿死(永远拿 到到筷子)的算法。
• 对上面的程序Байду номын сангаас行改进,完成题目(2)要求。
选做题:
• 根据以前做过的实验,把算法移植到给定的图形用户界 面(GUI)框架程序中,每个线程创建自己的窗口,每个哲 学家的吃饭和取筷子信息显示在自己的窗口界面中,每 个窗口中右键单击时开始取筷子和吃饭的过程。 • 为降低图形化开发的难度,可以只设计三个哲学家线程, 每个线程设计自己的线程函数(即不合并线程函数)。 • 执行时以各种顺序在三个窗口中右击,验证执行结果。
• 思考:改变放下左右两边的筷子的顺序会有影 响吗?验证执行。
程序改进二: 把三个线程函数合并成一个统一的线程函数,哲学家的编号由 线程的函数参数传入,根据前面的程序代码完成省咯号处的设 计,并完成主函数的相应修改。执行,记录结果。
DWORD WINAPI ThreadProc( LPVOID lpParameter ) { int index; index=*(int *)lpParameter; …… return 0; } int main() { int num=1; h_Thread[0]=CreateThread(NULL,0 ,ThreadProc,&num ,0,NULL); num++; h_Thread[1]=CreateThread(NULL,0 ,ThreadProc,&num ,0,NULL); num++; h_Thread[2]=CreateThread(NULL,0 ,ThreadProc,&num ,0,NULL); }
哲学家就餐问题解决死锁的三种思路
哲学家就餐问题是计算机科学中一个经典的同步问题,它描述了五位哲学家围坐在圆桌前就餐,每位哲学家必须先拿起右边的餐具再拿起左边的餐具,但每次只能有一位哲学家拿起餐具就餐。
这个问题的关键在于如何避免死锁,即所有哲学家都拿起了右边的餐具,然后等待拿左边餐具的哲学家放下右边的餐具。
为了解决这个问题,计算机科学家提出了三种思路。
第一种思路是引入一个“服务生”,服务生负责给哲学家提供餐具,每次只允许一个哲学家向服务生请求餐具,这样就可以避免死锁。
然而,这种方法可能会引入新的竞争条件,服务生可能会成为新的瓶颈,从而降低系统的效率。
第二种思路是引入资源分级,为了避免死锁,可以给每个哲学家的餐具加上编号,要求哲学家先拿编号较小的餐具,再拿编号较大的餐具。
这样就可以避免死锁,但是可能会增加系统的复杂性,需要管理更多的资源状态。
第三种思路是破坏死锁的四个必要条件之一。
死锁发生的四个必要条件分别是互斥、请求并持有、不可剥夺和循环等待。
为了避免死锁,可以破坏其中一个或多个条件。
可以引入超时机制,当哲学家拿到一个餐具后,一定时间内没有获得另一个餐具,就放下手中的餐具,避免形成循环等待。
这种方法可以在不增加系统复杂性的情况下有效地解决死锁问题。
在我看来,这三种思路各有优缺点,要根据具体的场景和需求选择合适的方法。
不同的问题可能需要采用不同的思路来解决,需要权衡各种因素来做出最佳的决策。
哲学家就餐问题是一个充满哲学思考的经典问题,它不仅考察了计算机科学中的同步与互斥问题,更可以引发我们对于资源分配、竞争条件和系统设计的深入思考。
通过对哲学家就餐问题的深入理解,我们可以更加灵活地运用不同的思路解决实际中的问题,让我们的系统更加健壮和高效。
结语:通过对哲学家就餐问题的深入探讨,我们可以发现在计算机科学中,解决死锁问题有很多种思路,每种思路都有其独特的优缺点。
只有充分理解这些思路并根据具体情况做出权衡,才能更好地解决实际中遇到的死锁问题。
哲学家就餐
利用记录型信号量解决:
• 进分析可知,放在桌子上 的筷子是临界资源,在一 段时间内允许一位哲学家 使用。为了实现对筷子的 互斥使用,可以用一个信 号量表示一只筷子,由这 五个信号量构成信号量数 组。其描述如下:
• • Var chopstick:array[0,…,4]of semaphore; 所有信号量均被初始化为1 ,第i 位哲学家的活动课描述为: • • • • • • • • • • • repeat: wait(chopstick[i]); Wait(chopstick[(i+1)mod5); … eat; … signal(chopstick[i]); signal(chopstick([i+1]mod5); … Think; until false
哲学家用餐
问题:
• 哲学家就餐问题中,一组哲学家围坐在一个圆 桌旁,每个哲学家的左边都只有一只筷子(当 然他的右边也有一只筷子,但是这是他右边哲 学家的左边的筷子),他们吃完了就思考,思 考了一会就会饿,饿了就想吃,然而,为了吃 饭,他们必须获得左边和右边的筷子进餐完毕, 放下筷子继续思考。
五个人五只筷子该如何进行用餐啊
(3)规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他 右边的筷子;而偶数号的哲学家则相反.按此规定,将是1,2号哲 学家竞争1号筷子,3,4号哲学家竞争3号筷子.即五个哲学家都 竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会1个哲 学家能获得两支筷子而进餐.其伪码为:
• • • • • • • • • • • Semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int i) { While(true) { Think(); If(i%2==0) //偶数号哲学家, 先右后左 { Wait(chopstick[i+1]mod5); Wait(chopsticl[i]); eat(); • • • • • • • • • • • • signal(chopstick[(i+1)]mod5); singal(chopstick[i]); } else { Wait(chopsticl[i]); Wait(chopstick[i+1]mod5); eat(); singal(chopstick[i]); signal(chopstick[(i+1)]mod5); } }
哲学家就餐问题的算法实现
哲学家就餐问题的算法实现在哲学家就餐问题中,假定有五位哲学家围坐在一张圆桌旁,每位哲学家面前都放着一碗意面和一把叉子。
这五位哲学家中的每位都有两种活动,一种是思考,一种是就餐。
但是,这五位哲学家只有五支叉子共用,也就是说,每个哲学家只能在自己左右两边分别拿起一把叉子。
若这五位哲学家中有若干人同时拿着左手边的叉子,或者同时拿着右手边的叉子,那么他们都无法就餐。
这时,就需要找到一种算法来解决这个问题。
解法一:Chandy/Misra解法Chandy/Misra解法是一种分布式算法,它的思路是使得每一位哲学家都向右边的人要叉子。
一旦它们都拿到了右边的叉子,就会开始就餐,然后把左右两个叉子都放回去。
这种算法的优点是它具有分布式系统的特点,不会造成资源竞争,而且在算法处理结束后,所有人都不会处于饥饿状态。
但是,这种算法实现的难度比较大,因为需要每个哲学家都向右边的人要叉子,而且需要考虑异常情况。
解法二:Dijkstra解法Dijkstra解法也被称为银行家算法,它的思路是让每一位哲学家先拿一支叉子,只有拿到两支叉子后,才可以开始就餐。
一旦就餐结束,哲学家就将叉子放回去。
这种算法的优点是它比较简单,易于实现。
但是,如果有一位哲学家先拿了一支叉子并且不再释放,那么其他哲学家就会陷入死锁状态。
解法三:Semaphore解法Semaphore解法是以信号量为基础的算法,它的思路是对每支叉子定义一个信号量,并使用信号量来控制哲学家与叉子之间的关系。
一旦一个哲学家想要就餐,就需要请求两个叉子的信号量,如果请求不到,则会被阻塞。
这种算法的优点是它具有可扩展性,而且可以支持多个进程同时使用资源。
但是,它比较复杂,可能会导致死锁。
结论在实际开发中,我们可以根据自己的需求选择合适的算法来解决哲学家就餐问题。
如果要求系统具有分布式系统的特点,可以使用Chandy/Misra解法;如果要求简单易行和易于实现,可以使用Dijkstra解法;如果要求可扩展性和支持多进程,可以选择Semaphore解法。
哲学家就餐问题
test(RIGHT(i));/*看右邻是否进餐*/
V(mutex);
}
}
利用管程机制实现(最终该实现是失败的,见以下分析):原理:不是对每只筷子设置信号量,而是对每个哲学家设置信号量。test()函数有以下作用:a.如果当前处理的哲学家处于饥饿状态且两侧哲学家不在吃饭状态,则当前哲学家通过test()函数试图进入吃饭状态。b.如果通过test()进入吃饭状态不成功,那么当前哲学家就在该信号量阻塞等待,直到其他的哲学家进程通过test()将该哲学家的状态设置为EATING。c.当一个哲学家进程调用put_forks()放下筷子的时候,会通过test()测试它的邻居,如果邻居处于饥饿状态,且该邻居的邻居不在吃饭状态,则该邻居进入吃饭状态。由上所述,该算法不会出现死锁,因为一个哲学家只有在两个邻座都不在进餐时,才允许转换到进餐状态。该算法会出现某个哲学家适终无法吃饭的情况,即当该哲学家的左右两个哲学家交替处在吃饭的状态的时候,则该哲学家始终无法进入吃饭的状态,因此不满足题目的要求。但是该算法能够实现对于任意多位哲学家的情况都能获得最大的并行度,因此具有重要的意义。
V(s[i]);
}
}பைடு நூலகம்
void get_forks(int i)
{
P(mutex);
state[i]=HUNGRY;
test(i);/*试图得到两支筷子*/
V(mutex);
P(s[i]);/*得不到筷子则阻塞*/
}
void put_forks(int i)
{
P(mutex);
state[i]=THINKING;
}
}
}
原理:规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号的哲学家则相反.按此规定,将是1,2号哲学家竞争1号筷子,3,4号哲学家竞争3号筷子.即五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获得两支筷子而进餐。而申请不到的哲学家进入阻塞等待队列,根FIFO原则,则先申请的哲学家会较先可以吃饭,因此不会出现饿死的哲学家。
哲学家进餐问题(操作系统)
哲学家进餐问题(操作系统)哲学家进餐问题(操作系统)1.简介1.1 背景介绍哲学家进餐问题是计算机科学中一个经典的并发问题,最早由Edsger Dijkstra在1965年提出。
1.2 问题描述问题的场景是五位哲学家围坐在一张圆桌前,每个哲学家面前有一碗饭和一根筷子。
哲学家需要交替地思考和进餐,但是他们只能使用左右两边的筷子来进餐。
1.3 目标设计一个算法来保证哲学家们能够交替地进餐,同时避免死锁和饥饿现象的发生。
2.解决方案2.1 简单解法一个简单的解法是给每个哲学家编号,规定奇数号哲学家先拿左边的筷子,偶数号哲学家先拿右边的筷子。
当一个哲学家需要拿筷子时,他会先检查他的两边是否有其他哲学家正在使用,如果没有,他就可以拿起两边的筷子进餐。
否则,他需要等待直到两边的筷子都可用。
2.2 改进解法上述简单解法可能会导致死锁问题。
为了避免死锁,我们可以引入资源分级的概念。
每个筷子被分为两个等级,分别是主要资源和次要资源。
哲学家需要按照顺序来获取资源,例如,先获取主要资源,然后获取次要资源。
3.算法实现3.1 数据结构我们可以使用一个数组来表示圆桌上的五个筷子,同时使用一个锁数组来表示每个筷子的状态(是否被占用)。
3.2 算法流程在哲学家进餐问题中,每个哲学家都需要经历思考和进餐两个过程,我们可以使用线程来模拟这两个过程。
4.算法分析4.1 死锁问题通过引入资源分级的概念,我们成功避免了死锁问题的发生。
每个哲学家按照顺序获取资源,不会出现他们都在等待同一个资源的情况。
4.2 饥饿问题在我们的算法中,每个哲学家都会交替地进餐和思考,因此不会出现饥饿问题。
5.附件本文档暂无附件。
6.法律名词及注释6.1 死锁死锁是指在并发系统中,两个或多个进程或线程无限期地互相等待对方所占有的资源的情形。
6.2 饥饿饥饿是指某个进程或线程因无法获得所需的资源而无法继续执行的情况。
哲学家进餐问题
8
哲学家进餐问题的应用
操作系统线程同步 生活中人行马路同步
9
感谢您的阅读收藏,谢谢!
7
解决问题的办法
A.原理:至多只允许四个哲学家同时进餐,以保 证至少有一个哲学家能够进餐,最终总会释放出他 所使用过的两支筷子,从而可使更多的哲学家进餐。 以下将room 作为信号量,只允许4 个哲学家同时 进入餐厅就餐,这样就能保证至少有一个哲学家 可以就餐,而申请进入餐厅的哲学家进入room 的 等待队列,根据FIFO 的原则,总会进入到餐厅就 餐,因此不会出现饿死和死锁的现象。
5
以上两个问题反映的是程序并发执行时进 程同步的两个关键问题:饥饿和死锁。为 了提高系统的处理能力和机器的利用率, 并发程序被广泛地使用,因此,必须彻底 解决并发程序执行中的死锁和饥饿问题。
6
于是,哲学家问题推广为更一般性的n个进 程和m个共享资源的问题,并在研究过程中 给出了解决这类的问题的不少方法和工具, 如Pertri网、并发程序设计语言等。
如何协调5位置学家的生活进程,使得每位 哲学家最终都可以进餐?
4
考虑下面的两种情况。
(1)哲学家的生活进程,当所有的哲学家都同时 拿起左手筷子时,则所有哲学家都将拿不到右手 筷子,并处于等待状态,那么,哲学家都将无法 进餐,最终饿死。
(2)将哲学家的生活进程修改为当拿不到右手筷 子时,就放下左手筷子。但是,可能在一个瞬间, 所有的哲学家都同时拿起左手筷子,则自然拿不 到右手筷子,于是同时放下左手筷子,等一会, 又同时拿起左手筷子,如此重复下去,则所有的 哲学家都将无法进餐。
哲学家进餐
哲学家供餐问题是计算机科学家递杰斯 特拉提出的,问题是这样描述的:人的面 前有一碗面条,碗的两旁各有一只筷子.假 设哲学家的生活除了吃饭就是思考问题, 吃饭的时候需要左手拿一只筷子,右手拿 一只筷子,然后开始进餐。吃完后将两只 筷子放回原处,继续思考问题。
哲学家就餐问题解释
哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步(Synchronization)时产生的问题。
在1971年,著名的计算机科学家艾兹格·迪科斯彻提出了一个同步问题,即假设有五台计算机都试图访问五份共享的磁带驱动器。
稍后,这个问题被托尼·霍尔重新表述为哲学家就餐问题。
这个问题可以用来解释死锁和资源耗尽。
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。
吃东西的时候,他们就停止思考,思考的时候也停止吃东西。
餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。
因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。
他们只能使用自己左右手边的那两只餐叉。
哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。
哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。
即使没有死锁,也有可能发生资源耗尽。
例如,假设规定当哲学家等待另一只餐叉超过五分钟后就放下自己手里的那一只餐叉,并且再等五分钟后进行下一次尝试。
这个策略消除了死锁(系统总会进入到下一个状态),但仍然有可能发生“活锁”。
如果五位哲学家在完全相同的时刻进入餐厅,并同时拿起左边的餐叉,那么这些哲学家就会等待五分钟,同时放下手中的餐叉,再等五分钟,又同时拿起这些餐叉。
在实际的计算机问题中,缺乏餐叉可以类比为缺乏共享资源。
一种常用的计算机技术是资源加锁,用来保证在某个时刻,资源只能被一个程序或一段代码访问。
当一个程序想要使用的资源已经被另一个程序锁定,它就等待资源解锁。
当多个程序涉及到加锁的资源时,在某些情况下就有可能发生死锁。
例如,某个程序需要访问两个文件,当两个这样的程序各锁了一个文件,那它们都在等待对方解锁另一个文件,而这永远不会发生。
[编辑]服务生解法一个简单的解法是引入一个餐厅服务生,哲学家必须经过他的允许才能拿起餐叉。
有效的解决哲学家就餐问题的方法
有效的解决哲学家就餐问题的方法有效的解决哲学家就餐问题的方法引言哲学家就餐问题是一个经典的并发算法问题,描述了五个哲学家围坐在圆桌旁,需要通过共享的筷子来进行进餐的场景。
在这个问题中,每个哲学家需要交替地进行思考和进餐,而他们的进餐需要两根筷子。
解决方法为了有效地解决哲学家就餐问题,我们可以采用以下几种方法:1.资源分级分配:引入一个资源分级机制,确保每个哲学家在进餐时仅能获得特定的筷子,而非两根。
这样一来,将不会出现所有哲学家同时拿起自己左边的筷子的情况,从而避免死锁。
2.奇偶策略:将哲学家分为奇数和偶数两组,奇数组先尝试获取左边的筷子,偶数组先尝试获取右边的筷子。
通过交替获取筷子的方式,可以避免所有哲学家同时获取同一边筷子的情况,降低死锁可能性。
3.资源分配顺序:当一个哲学家准备就餐时,他需要按照特定的顺序获取筷子,而不是随机选择。
通过确定筷子获取的顺序,可以规避潜在的死锁情况。
4.资源抢占:引入资源抢占的机制,当一个哲学家尝试获取筷子时,如果发现对应的筷子已被其他哲学家占用,他可以选择尝试获取其他筷子,或者等待一段时间后再次尝试。
这样可以有效避免死锁,并提高吞吐量。
5.动态调整资源:根据当前进餐的哲学家数量,动态调整可用的筷子资源。
当哲学家数量较少时,可以减少筷子的个数,避免资源浪费;当数量较多时,则需要增加筷子的个数,保证所有哲学家都能同时用餐。
结论哲学家就餐问题是一个常见的并发问题,通过采用上述方法中的一种或多种,可以有效解决死锁和资源浪费的问题,提高整体的系统效率和可靠性。
在实际应用中,需要根据场景的具体需求和系统特点选择合适的方法,并进行适当优化。
6.基于信号量的解决方案:使用信号量作为同步工具,每个哲学家尝试获取筷子时需要先获取两个信号量,表示左右两只筷子的可用性。
当某个哲学家无法获取到两个信号量时,则放弃当前的操作,等待一段时间后再次尝试。
这种方法可以有效防止死锁的发生。
7.餐位限制:通过限制同时进餐的哲学家人数来解决就餐问题。
经典同步问题(哲学家进餐等)
模型分析
• (1)生产者进行生产将物品放入仓库,同一时 间只能有一个生产者将物品放入仓库,若仓库满, 生产者将等待; • (2)消费者从仓库中取出物品,同一时间只能 有一个消费者取出物品,若仓库空,消费者等待; • (3)生产者将物品放入仓库时消费者不能同时 取; • (4)消费者取物品时生产者不能放入物品。
三个进程工作过程如下图所示:
解题步骤
• (2)确定互斥信号量的个数、含义 • (3)用P、V操作描述关系
问题提出
有5个哲学家他们围坐在一张圆桌旁,每 人面前有一菜盘,各菜盘之间有一根筷子。 每个哲学家或思考问题或就餐,当思考 问题时放下筷子,饥饿的时候就吃菜。 想要夹菜时必须获得两根筷子,且每人 只能从自己的左边和右边去取筷子,只有 在他拿到两只筷子时才能进餐。就餐后放 下筷子以供别人使用,自己继续思考问题。
哲学家5号
5
无论4号5号谁 得到4号筷子,都 有一个可以进餐
2 哲学家3号
4
而5号没有人 与他竞争,得 若4号在与3号的竞 到左边的筷 争中没有得到筷子, 子 则5号得到4号筷子, 进餐
若4号在与3号 的竞争中得到 哲学家4号 筷子,则与5号 竞争4号筷子.
问题提出
某数据库有一个写进程、多个读进程, 它们之间读、写操作的互斥要求是:写进 程运行时,其他读、写进程不能对数据库 进行操作。读进程之间不互斥,可以同时 读数据库。请用信号量及PV操作描述这一 组进程的工作过程。
问题分析
所以,为了实现生产者进程和消费者进 程的同步与互斥,设置三个信号量: 两个同步信号量empty和full, 一个互斥信号量mutex, 并在这三个信号量上施加正确的P、V 操作,就可保障两进程正确无误地运行。
哲学家就餐问题
管程机制
1. 管程可以看做一个软件模块,它是将共享 的变量和对于这些共享变量的操作封装起 来,形成一个具有一定接口的功能模块, 进程可以调用管程来实现进程级别的并发 控制。 2. 进程只能互斥的使用管程,即当一个进程 使用管程时,另一个进程必须等待,当一 个进程使用完管程后,它必须释放管程并 唤醒等待管程的另一个管程。
一、哲学家就餐问题与C语言:
• 死锁问题
• 其实呢,这个问题在我们计算机中也经常遇到, 用户需要的特定信息由几部分组成,而几个用户 各掌握了特定信息的一部分,彼此不放手,导致 持续的等待我们称之为死锁。在我们学习了哲学 家就餐问题之后,我们可以轻松地解决这个问题
死锁问题解决方法:
(1)至多只允许四个哲学家同时进餐,以保证至少有一个哲学家 能够进餐,最终总会释放出他所使用过的两支筷子,从而可 使更多的哲学家进餐. (2)仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子 进餐. (3)规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他 右边的筷子;而偶数号的哲学家则相反.按此规定,将是1,2号 哲学家竞争1号筷子,3,4号哲学家竞争3号筷子.即五个哲学 家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总 会有一个哲学家能获得两支筷子而进餐.
Chandy/Misra解法
• 1984年,K. Mani Chandy和J. Misra提出了哲学家就餐问题的另一个解 法,允许任意的用户(编号P1, ..., Pn)争用任意数量的资源。与迪科 斯彻的解法不同的是[来源请求],这里编号可以是任意的。 • 1.对每一对竞争一个资源的哲学家,新拿一个餐叉,给编号较低的哲 学家。每只餐叉都是“干净的”或者“脏的”。最初,所有的餐叉都 是脏的。 • 2.当一位哲学家要使用资源(也就是要吃东西)时,他必须从与他竞 争的邻居那里得到。对每只他当前没有的餐叉,他都发送一个请求。 • 3.当拥有餐叉的哲学家收到请求时,如果餐叉是干净的,那么他继续 留着,否则就擦干净并交出餐叉。 • 4.当某个哲学家吃东西后,他的餐叉就变脏了。如果另一个哲学家之 前请求过其中的餐叉,那他就擦干净并交出餐叉。 • 这个解法允许很大的并行性,适用于任意大的问题。
有效的解决哲学家就餐问题的方法
有效的解决哲学家就餐问题的方法
哲学家就餐问题是一个经典的并发编程问题,旨在探讨资源竞争和死锁等并发编程中的困境。
这个问题涉及一组哲学家坐在圆桌周围,并尝试进行思考和就餐。
每个哲学家之间有一只餐叉,而就餐需要同时拿到两只餐叉。
问题的关键在于如何确保每个哲学家都能成功就餐,同时避免死锁情况的发生。
以下是一些有效的解决哲学家就餐问题的方法:
1. 资源分级分配:引入资源分级分配的概念,让哲学家按照顺序获取餐叉。
例如,可以规定哲学家必须先拿起左边的餐叉,再拿起右边的餐叉,或者规定只有在两边的餐叉都可用时才可以同时拿起。
2. 割舍法:引入一个资源管理者(或者称为仲裁者),负责控制哲学家的资源访问。
当哲学家要就餐时,必须向资源管理者申请获取餐叉的许可。
资源管理者可以限制同时就餐的哲学家数量,避免资源竞争和死锁。
3. 破坏循环等待条件:每个哲学家都可以按照固定的顺序去获取餐叉,比如按照序号从小到大的顺序。
这样可以避免出现所有哲学家都拿起了一个餐叉但无法获取到第二只餐叉的死锁情况。
4. 引入超时机制:设置一个超时时间,在等待获取餐叉的过程中如果超过了超时时间仍未获得所需资源,哲学家将释放已经获得的资源并稍后再试,以避免陷入死锁。
5. 资源共享与互斥:使用信号量、互斥锁或其他并发编程机制,确保每次只有一个哲学家可以访问餐叉,其他哲学家必须等待。
这些方法都有助于解决哲学家就餐问题中的资源竞争和死锁情况。
但需要注意的是,并发编程问题的解决方法可能会因编程语言、操作系统和具体情境而有所不同,因此在实际应用中需要根据具体情况选择和调整解决方案。
[精彩]哲学家就餐题目
一、问题描述:有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃通心粉.为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子二、本程序防止死锁发生采取的措施:仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子。
这样要么一次占有两只筷子(所有线程需要的资源)进行下一步的吃通心粉,然后释放所有的资源;要么不占用资源,这样就不可能产生死锁了。
三、产生死锁的分配方式:当筷子(资源)可用时,先分配左边的筷子,等待一会后再分配右边的筷子,由于这个过程中,左边的筷子一直没有释放,就有可能产生死锁了。
四、程序运行说明程序运行过程中会弹出一个MessageBox提示操作者操作:1.第一个对话框用于选择运行模式a.选择yes 表示采用的是运行的防止死锁的方式,这样的话整个程序可以一直运行下去,不会产生死锁。
b.选择no 表示运行产生死锁的方式会弹出第二个对话框。
2.第二个对话框用于选择运行时,线程运行的时间a. 选择 yes 线程时间比较短,很快就可以死锁b.选择no 线程时间跟选择yes 时候的时间差不多,产生死锁的时间稍微长一点五、关于哲学家就餐问题的mfc程序分析:A. Dining.c变量说明:函数说明:B.Mutex.c函数说明:1. DWORD WINAPI PhilosopherThread(LPVOID pVoid)哲学家进程:用于分配给哲学家筷子(资源)通过开始运行时候的对话框的选择来控制资源的分配方式:两中分配方式见二、三所述。
通过随机产生的时间来控制线程的运行,每个哲学家的状态都是resting waiting eating,一直循环。
2.int Diner(void)用于建立互斥的信号对象(筷子)和启动哲学家进程。
哲学家就餐问题
03
问题的基本描述
描述问题的具体内容
哲学家就餐问题的背景
问题的具体描述:哲学家就餐问题的描述和场景
问题的解决思路:如何解决哲学家就餐问题
问题的启示:哲学家就餐问题对人工智能和计算机科学的影响和启示
解释问题中的关键概念
哲学家就餐问题:描述了哲学家在吃饭时如何避免死锁的问题
意义:哲学家就餐问题不仅是一个理论问题,更是一个具有现实意义的问题。通过研究和探讨这个问题,我们可以更好地理解现实生活中的资源分配和优先级排序等问题,并找到更好的解决方案。
07
总结与展望
总结哲学家就餐问题的核心内容和解决方案
核心内容:哲学家就餐问题的本质是死锁问题,涉及到多个哲学家同时竞争有限的资源,导致系统无法继续运行。
哲学家就餐问题的应用:如“哲学家就餐问题在计算机科学中的应用”、“哲学家就餐问题在人工智能领域的应用”等。
哲学家就餐问题的启示:如“哲学家就餐问题对计算机科学的启示”、“哲学家就餐问题对人工智能的启示”等。
探讨如何深化对哲学家就餐问题的理解
了解问题的背景和起源
探讨问题在现实生活中的应用和意义
思考问题对未来发展的影响和价值
添加标题
添加标题
添加标题
添加标题
哲学家就餐问题解决方案:优点是解决了死锁问题,缺点是实现较为复杂。
0-1筷子解决方案:优点是简单直观,缺点是可能导致死锁。
信号量解决方案:优点是避免了死锁,缺点是实现较为复杂。
管程解决方案:优点是简单直观,缺点是可能导致死锁。
探讨解决方案的实际应用
解决方案的扩展应用:多线程同步问题
问题的起源:起源于古希腊哲学家苏格拉底的故事
哲学家就餐问题解决方案
哲学家就餐问题解决方案
1. 哎呀呀,哲学家就餐问题啊!咱可以试试这样,就像拼图一样,把各种口味、各种菜品都摆在一起,看看能不能拼成一个完美的“美食地图”。
比如柏拉图喜欢思考,那就给他来一份精致的沙拉,边吃边想呗。
2. 嘿,为什么不搞个主题餐厅呢?像开个“哲学沙龙餐厅”,大家边吃边探讨深奥的问题呀。
就好像孔子和他的弟子们围坐一起讲学吃饭那样,多有意思!苏格拉底肯定超爱这种氛围。
3. 要不,给哲学家们来个定制菜单吧!根据他们的哲学理念来配餐,这不是超酷吗?老子主张自然无为,那就给他上些清淡自然的食物。
这就好像为他们量身打造的衣服一样合适。
4. 哎呀,我们可以搞些哲学趣味餐具呀!比如餐盘上印着各种哲学名言,吃着吃着还能激发灵感呢。
这不就跟阿基米德在浴缸里发现浮力原理似的嘛!
5. 或者,举办哲学美食节怎么样?把哲学家们喜欢的食物都集中起来,那场面,肯定火爆。
这就如同一场哲学的盛宴,亚里士多德肯定会成为其中最闪亮的嘉宾。
6. 让服务员也都变成哲学小达人呀,能和哲学家们聊聊哲学顺便推荐菜品。
就像伯牙子期遇到懂他音乐的人一样,多棒!尼采遇到这样的服务员想必也会很开心。
7. 可以建个哲学美食交流群呀,大家在里面分享好吃的和哲学见解。
这不就相当于给哲学家们搭了个专属的交流平台嘛,毕达哥拉斯肯定会积极发言的。
8. 干脆来个哲学厨艺大比拼吧,让哲学家们也参与进来。
这多好玩呀,就好像他们在哲学战场上辩论一样激烈。
我觉得要解决哲学家就餐问题,就得有创意又有趣,让他们在享受美食的同时也能沉浸在哲学的氛围里。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机操作系统哲学家进餐问题的研究姓名:陆文静学号: 1310750012 指导老师:杨婷婷专业班级:软件工程1301班完成时间: 2015年5月4日哲学家进餐问题研究摘要:一、问题的描述哲学家就餐问题是一种典型的同步问题,它是由Dijkstra提出并解决的。
该问题描述如下:有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐。
设五个哲学家分别编号为A,B,C,D,E,桌子上放着五只筷子,筷子分别编号为0,1,2,3,4,桌子中央有一盘饭菜,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。
进餐毕,放下筷子继续思考。
二、解决问题的方案1、算法描述semaphore chopstick[5]={1,1,1,1,1};do{wait(room);wait(chopstick[i]);wait(chopstick[(i+1)%5]);eat();signal(chopstick[i]);signal(chopstick[(i+1)%5]);signal(room);Think;} while[ture];以上描述中,可保证不会有两个相邻的哲学家同时进餐,但却有可能引起死锁。
假如五位哲学家同时饥饿而各自拿起左边的筷子时,就会使五个信号量chopstick均为0;当他们试图拿右边的筷子时,豆浆因无筷子可拿而无限期地等待,进入死锁状态。
2、改进算法描述描述一种没有人饿死算法,考虑了四种实现的方式(A、B、C、D)A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。
以下将room 作为信号量,只允许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会出现饿死和死锁的现象。
伪码:semaphore chopstick[5]={1,1,1,1,1};semaphore room=4;void philosopher(int i){while(true){think();wait(room); //请求进入房间进餐wait(chopstick[i]); //请求左手边的筷子wait(chopstick[(i+1)%5]); //请求右手边的筷子eat();signal(chopstick[(i+1)%5]); //释放右手边的筷子signal(chopstick[i]); //释放左手边的筷子signal(room); //退出房间释放信号量room}}B.原理:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。
方法1:利用AND 型信号量机制实现:根据课程讲述,在一个原语中,将一段代码同时需要的多个临界资源,要么全部分配给它,要么一个都不分配,因此不会出现死锁的情形。
当某些资源不够时阻塞调用进程;由于等待队列的存在,使得对资源的请求满足FIFO 的要求,因此不会出现饥饿的情形。
伪码:semaphore chopstick[5]={1,1,1,1,1};void philosopher(int I){while(true){think();Swait(chopstick[(I+1)]%5,chopstick[I]);eat();Ssignal(chopstick[(I+1)]%5,chopstick[I]);}}方法2:利用信号量的保护机制实现。
通过信号量mutex对eat()之前的取左侧和右侧筷子的操作进行保护,使之成为一个原子操作,这样可以防止死锁的出现。
伪码:semaphore mutex = 1 ;semaphore chopstick[5]={1,1,1,1,1};void philosopher(int i){ while(true){ think();wait(mutex);wait(chopstick[(i+1)]%5);wait(chopstick[i]);signal(mutex);eat();signal(chopstick[(i+1)]%5);signal(chopstick[i]);}}C、原理:规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号的哲学家则相反.按此规定,将是1,2号哲学家竞争1号筷子,3,4号哲学家竞争3号筷子.即五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获得两支筷子而进餐。
而申请不到的哲学家进入阻塞等待队列,根FIFO原则,则先申请的哲学家会较先可以吃饭,因此不会出现饿死的哲学家。
伪码:semaphore chopstick[5]={1,1,1,1,1};void philosopher(int i){while(true){think();if(i%2 == 0) //偶数哲学家,先右后左。
{wait (chopstick[ i + 1 ] mod 5) ;wait (chopstick[ i]) ;eat();signal (chopstick[ i + 1 ] mod 5) ;signal (chopstick[ i]) ;}else //奇数哲学家,先左后右。
{wait (chopstick[ i]) ;wait (chopstick[ i + 1 ] mod 5) ;eat();signal (chopstick[ i]) ;signal (chopstick[ i + 1 ] mod 5);}}* 进一步改进B方法一的操作算法设计了一个test过程,如果通过了text过程,线程可进入吃饭过程,否则让,线程进入等待状态。
通过text过程,则该哲学家左右筷子设置为不可用标志,阻止其相邻哲学家通过text过程,这实际上表示该哲学家需要的两只筷子已指定给他,即预先分配全部资源,公用信号量mutex作用的范围仅限text过程,大大小于改进之前的方法。
改进算法描述如下:Semabore chopstick[0]=chopstick[1]=chopstick[2]=chopstick[3]= chopstick[4]=1; Semaphore mutex=1;Boolean chop[0]=chop[1]=chop[2]=chop[3]=chop[4]=ture;Philosopher i’While(ture){思考;While(!Test(i)){等待};//如果测试不通过,处于等待状态,知道测试通过P(chopstick[i]);P(chopstick[(i+1)%5]);吃饭;V(chopstick[i]);V(chopstick[i+1]);chop[i]=chop[(i+1)%5]=ture;//设置这两只筷子可用标志通知;//通知从等待状态进入测试状态}boolean test(int i){P(mutex);//公用信号量,用于测试过程的互斥if(chop[i]&&chop[(i+1)%5]){Chop[i]=chop[(i+1)%5]=false;//设置这两只筷子不可用标志Return true;} else {Return false;}V(mutex);}三、总结1、算法的总结哲学家就餐问题是个经典的同步问题,题中的演示哲学家从来不交谈,这就可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。
即使没有死锁,也有可能发生资源耗尽。
例如,假设规定当哲学家等待另一只餐叉超过五分钟后就放下自己手里的那一只餐叉,并且再等五分钟后进行下一次尝试。
这个策略消除了死锁(系统总会进入到下一个状态),但仍然有可能发生“活锁”。
如果五位哲学家在完全相同的时刻进入餐厅,并同时拿起左边的餐叉,那么这些哲学家就会等待五分钟,同时放下手中的餐叉,再等五分钟,又同时拿起这些餐叉。
在实际的计算机问题中,缺乏餐叉可以类比为缺乏共享资源。
一种常用的计算机技术是资源加锁,用来保证在某个时刻资源只能被一个程序或一段代码访问。
当一个程序想要使用的资源已经被另一个程序锁定,它就等待资源解锁。
当多个程序涉及到加锁的资源时,在某些情况下就有可能发生死锁。
例如,某个程序需要访问两个文件,当两个这样的程序各锁了一个文件,那它们都在等待对方解锁另一个文件,而这永远不会发生。
[解法] 服务生解法一个简单的解法是引入一个餐厅服务生,哲学家必须经过他的允许才能拿起餐叉。
因为服务生知道哪只餐叉正在使用,所以他能够作出判断避免死锁。
为了演示这种解法,假设哲学家依次标号为A至E。
如果A和C在吃东西,则有四只餐叉在使用中。
B坐在A和C之间,所以两只餐叉都无法使用,而D和E之间有一只空余的餐叉。
假设这时D想要吃东西。
如果他拿起了第五只餐叉,就有可能发生死锁。
相反,如果他征求服务生同意,服务生会让他等待。
这样,我们就能保证下次当两把餐叉空余出来时,一定有一位哲学家可以成功的得到一对餐叉,从而避免了死锁。
[解法] 资源分级解法另一个简单的解法是为资源(这里是餐叉)分配一个偏序或者分级的关系,并约定所有资源都按照这种顺序获取,按相反顺序释放,而且保证不会有两个无关资源同时被同一项工作所需要。
在哲学家就餐问题中,资源(餐叉)按照某种规则编号为1至5,每一个工作单元(哲学家)总是先拿起左右两边编号较低的餐叉,再拿编号较高的。
用完餐叉后,他总是先放下编号较高的餐叉,再放下编号较低的。
在这种情况下,当四位哲学家同时拿起他们手边编号较低的餐叉时,只有编号最高的餐叉留在桌上,从而第五位哲学家就不能使用任何一只餐叉了。
而且,只有一位哲学家能使用最高编号的餐叉,所以他能使用两只餐叉用餐。
当他吃完后,他会先放下编号最高的餐叉,再放下编号较低的餐叉,从而让另一位哲学家拿起后边的这只开始吃东西。
尽管资源分级能避免死锁,但这种策略并不总是实用的,特别是当所需资源的列表并不是事先知道的时候。
例如,假设一个工作单元拿着资源3和5,并决定需要资源2,则必须先要释放5,之后释放3,才能得到2,之后必须重新按顺序获取3和5。
对需要访问大量数据库记录的计算机程序来说,如果需要先释放高编号的记录才能访问新的记录,那么运行效率就不会高,因此这种方法在这里并不实用。
这种方法经常是实际计算机科学问题中最实用的解法,通过为分级锁指定常量,强制获得锁的顺序,就可以解决这个问题。
2、拓展应用读者-写者问题第一和第二读者-写者问题是并行计算的模拟。
这两个问题描述的是有许多线程必须同时访问共享的内存地址,有的要读,有的要写。