哲学家就餐问题

合集下载

6个哲学家进餐问题预防死锁

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 操作。
死锁,但是处于不安全状态

5位哲学家进餐的问题

5位哲学家进餐的问题

模拟5位哲学家进餐的问题2008-04-21 21:241)问题描述学操作系统的进程同步都要涉及到三个经典问题:生产者-消费者问题、读者-写者问题和哲学家就餐问题。

下面来介绍一下哲学家就餐问题:哲学家就餐问题中,一组哲学家围坐在一个圆桌旁,每个哲学家的左边都只有一只筷子(当然他的右边也有一只筷子,但是这是他右边哲学家的左边的筷子),他们吃完了就思考,思考了一会就会饿,饿了就想吃,然而,为了吃饭,他们必须获得左边和右边的筷子。

当每个哲学家只拿有一只筷子的时候,会坐者等另一只筷子,在每个哲学家都只拿一个筷子的时候,就会发生死锁。

用C或C++, 来模拟5位哲学家进餐的问题。

2)关于源码的一点说明:vc6下源码测试通过运行,不过不能模拟死锁为每个哲学家使用POSIX线程(pthread)建立独立的线程(有独立的id),用互斥(叉子其他哲学家使用时,另一个哲学家不能使用)和条件(哲学家饿了才尝试去得到叉子,得到相邻的左右两把叉子才能进餐)来分到叉子。

关键事件:1. 哲学家饿了就要尝试去得到叉子。

2. 哲学家得到相邻的左右两把叉子才可以进餐3. 吃完了就要释放两把叉子每个事件发生就打印一行。

并用gettimeofday()显示毫秒。

A. 用'X' 表示哲学家在进餐B. 用'O' 表示哲学家在思考C. 用'!' 表示哲学家饿了例子:1 2 3 4 50 ms: O O O O O95 ms: ! O O O O95 ms: X O O O O214 ms: X O O O !327 ms: X O O ! !328 ms: X O O X !444 ms: O ! O O !444 ms: O X O O X(注意:肯定不会有两个X出现在相邻的列中)程序在运行“50次成功进餐”发生后停止。

哲学家在“进餐”和“思考”的“时间周期”是一个0.1到0.5之间的随机数字。

哲学家进餐问题的趣味例子

哲学家进餐问题的趣味例子

哲学家进餐问题的趣味例子
哲学家进餐问题是一个经典的计算机科学问题,用来展示并发编程中可能出现
的资源竞争和死锁问题。

这个问题的描述是:五位哲学家围坐在一张圆桌前,每位哲学家面前有一碗意面,但他们之间共享一把只能被一个人同时使用的餐叉。

每位哲学家需要先拿起右手边的餐叉,再拿起左手边的餐叉才能吃饭,吃完后放下餐叉继续思考问题。

如果哲学家之间同时试图拿起自己左右手边的餐叉,就会导致死锁问题,无法继续进餐。

这个问题的趣味例子在于通过这种抽象的场景,展现了并发编程中常见的竞争
和死锁问题。

实际上,哲学家进餐问题也可以被看作是对资源管理和同步机制的一种考验。

如果每位哲学家都按照固定的顺序拿餐叉,就不会发生死锁;而如果哲学家们都随机地尝试拿餐叉,就可能会出现资源竞争的问题,导致无法进餐。

这个问题的趣味之处在于,通过一个简单的场景,展示了复杂的并发编程中可
能出现的问题,让人们更加深入地理解并发编程中的挑战和技巧。

通过哲学家进餐问题的讨论,人们可以思考如何设计合理的同步机制和资源管理策略,避免竞争和死锁问题的发生,提高程序的并发性能和稳定性。

总的来说,哲学家进餐问题是一个充满趣味和启发的例子,能够帮助人们更好
地理解并发编程中的难点,同时也能够激发人们对于解决问题的创造力和思考能力。

通过这个例子的讨论,人们可以不仅仅学到技术知识,更能够培养出解决问题的能力和思维方式,为未来的学习和工作打下坚实的基础。

愿每位哲学家都能够顺利进餐,思考问题,探索未知的世界。

哲学家进餐问题

哲学家进餐问题

哲学家进餐问题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); }

哲学家就餐问题解决死锁的三种思路

哲学家就餐问题解决死锁的三种思路

哲学家就餐问题是计算机科学中一个经典的同步问题,它描述了五位哲学家围坐在圆桌前就餐,每位哲学家必须先拿起右边的餐具再拿起左边的餐具,但每次只能有一位哲学家拿起餐具就餐。

这个问题的关键在于如何避免死锁,即所有哲学家都拿起了右边的餐具,然后等待拿左边餐具的哲学家放下右边的餐具。

为了解决这个问题,计算机科学家提出了三种思路。

第一种思路是引入一个“服务生”,服务生负责给哲学家提供餐具,每次只允许一个哲学家向服务生请求餐具,这样就可以避免死锁。

然而,这种方法可能会引入新的竞争条件,服务生可能会成为新的瓶颈,从而降低系统的效率。

第二种思路是引入资源分级,为了避免死锁,可以给每个哲学家的餐具加上编号,要求哲学家先拿编号较小的餐具,再拿编号较大的餐具。

这样就可以避免死锁,但是可能会增加系统的复杂性,需要管理更多的资源状态。

第三种思路是破坏死锁的四个必要条件之一。

死锁发生的四个必要条件分别是互斥、请求并持有、不可剥夺和循环等待。

为了避免死锁,可以破坏其中一个或多个条件。

可以引入超时机制,当哲学家拿到一个餐具后,一定时间内没有获得另一个餐具,就放下手中的餐具,避免形成循环等待。

这种方法可以在不增加系统复杂性的情况下有效地解决死锁问题。

在我看来,这三种思路各有优缺点,要根据具体的场景和需求选择合适的方法。

不同的问题可能需要采用不同的思路来解决,需要权衡各种因素来做出最佳的决策。

哲学家就餐问题是一个充满哲学思考的经典问题,它不仅考察了计算机科学中的同步与互斥问题,更可以引发我们对于资源分配、竞争条件和系统设计的深入思考。

通过对哲学家就餐问题的深入理解,我们可以更加灵活地运用不同的思路解决实际中的问题,让我们的系统更加健壮和高效。

结语:通过对哲学家就餐问题的深入探讨,我们可以发现在计算机科学中,解决死锁问题有很多种思路,每种思路都有其独特的优缺点。

只有充分理解这些思路并根据具体情况做出权衡,才能更好地解决实际中遇到的死锁问题。

哲学家就餐问题的算法实现

哲学家就餐问题的算法实现

哲学家就餐问题的算法实现在哲学家就餐问题中,假定有五位哲学家围坐在一张圆桌旁,每位哲学家面前都放着一碗意面和一把叉子。

这五位哲学家中的每位都有两种活动,一种是思考,一种是就餐。

但是,这五位哲学家只有五支叉子共用,也就是说,每个哲学家只能在自己左右两边分别拿起一把叉子。

若这五位哲学家中有若干人同时拿着左手边的叉子,或者同时拿着右手边的叉子,那么他们都无法就餐。

这时,就需要找到一种算法来解决这个问题。

解法一:Chandy/Misra解法Chandy/Misra解法是一种分布式算法,它的思路是使得每一位哲学家都向右边的人要叉子。

一旦它们都拿到了右边的叉子,就会开始就餐,然后把左右两个叉子都放回去。

这种算法的优点是它具有分布式系统的特点,不会造成资源竞争,而且在算法处理结束后,所有人都不会处于饥饿状态。

但是,这种算法实现的难度比较大,因为需要每个哲学家都向右边的人要叉子,而且需要考虑异常情况。

解法二:Dijkstra解法Dijkstra解法也被称为银行家算法,它的思路是让每一位哲学家先拿一支叉子,只有拿到两支叉子后,才可以开始就餐。

一旦就餐结束,哲学家就将叉子放回去。

这种算法的优点是它比较简单,易于实现。

但是,如果有一位哲学家先拿了一支叉子并且不再释放,那么其他哲学家就会陷入死锁状态。

解法三:Semaphore解法Semaphore解法是以信号量为基础的算法,它的思路是对每支叉子定义一个信号量,并使用信号量来控制哲学家与叉子之间的关系。

一旦一个哲学家想要就餐,就需要请求两个叉子的信号量,如果请求不到,则会被阻塞。

这种算法的优点是它具有可扩展性,而且可以支持多个进程同时使用资源。

但是,它比较复杂,可能会导致死锁。

结论在实际开发中,我们可以根据自己的需求选择合适的算法来解决哲学家就餐问题。

如果要求系统具有分布式系统的特点,可以使用Chandy/Misra解法;如果要求简单易行和易于实现,可以使用Dijkstra解法;如果要求可扩展性和支持多进程,可以选择Semaphore解法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验一一、实验名称:哲学家就餐问题的实现二、实验学时:2三、实验内容和目的:实验目的:实现哲学家就餐问题,要求不能出现死锁。

通过本实验熟悉Linux系统的基本环境,了解Linux下进程和线程的实现。

实验内容:在Unix系统下实现教材2.4.2节中所描述的哲学家就餐问题。

要求显示出每个哲学家的工作状态,如吃饭,思考。

连续运行30次以上都未出现死锁现象。

四、实验原理:由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。

该问题是描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐。

平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。

进餐完毕,放下筷子继续思考。

五、实验器材(设备、元器件)(1)学生每人一台PC,安装WindowsXP/2000操作系统。

(2)局域网络环境。

(3)个人PC安装VMware虚拟机和Ubuntu系统。

六、实验内容:(一)熟悉Ubuntu系统下的多线程编程。

(二)实现哲学家就餐问题1. 算法思想规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子,而偶数号哲学家则相反。

按此规定,将是1、2号哲学家竞争1号筷子;3、4号哲学家竞争3号筷子。

即五位哲学家都生竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一位哲学家能获得两只筷子而进餐。

2. 流程图3. 程序代码(重要代码请注释)#include <stdio.h>#include <pthread.h>#include <semaphore.h>#include <stdlib.h>#include <string.h>#define NOC 5 //number of chopstic#define NOP 5 //number of philosophersem_t chopstic[NOC]; //semaphoreint flag[5]; //philosopher's statusvoid *eat(int i){int position;int temp = 0;int j = (i+1)%NOC;position = i%2;while(1){if(position == 0){ //odd take left firstsem_wait(&chopstic[i]);printf("philosopher%d get %d\n", i, i);sem_wait(&chopstic[j]);printf("philosopher%d get %d\n", i, j);flag[i] = 1; //philosopher is eatingprintf("waitting:"); //print others' statuswhile(temp < 5){if(!flag[temp])printf("philosopher%d\t", temp);temp++;}temp = 0;printf("\n");printf("eating:");// print others' statuswhile(temp < 5){if(flag[temp])printf("philosopher%d\t", temp);temp++;}printf("\n\n");temp = 0;//printf("\nphilosopher%d is eating\n\n", i); sleep(2);flag[i] = 0;printf("philosopher%d put %d\n", i, i); sem_post(&chopstic[i]);printf("philosopher%d put %d\n", i, j); sem_post(&chopstic[j]);}else{ //even take right firstsem_wait(&chopstic[j]);printf("philosopher%d get %d\n", i, j);sem_wait(&chopstic[i]);printf("philosopher%d get %d\n", i, i);flag[i] = 1;printf("waitting:");while(temp < 5){if(!flag[temp])printf("philosopher%d\t", temp);temp++;}temp = 0;printf("\n");printf("eating:");while(temp < 5){if(flag[temp])printf("philosopher%d\t", temp);temp++;printf("\n\n");temp = 0;//printf("\nphilosopher%d is eating\n\n", i);sleep(2);flag[i] = 0;printf("philosopher%d put %d\n", i, j);sem_post(&chopstic[j]);printf("philosopher%d put %d\n", i, i);sem_post(&chopstic[i]);}}}int main(void){int i = 0;int error;pthread_t philosopher[NOP];//init semwhile(i < 5){flag[i] = 0;sem_init(&chopstic[i], 0, 1);i++;}i = 0;//create threadwhile(i < 5){error = pthread_create(&philosopher[i], NULL, (void *)eat, (void *)i);if(error){printf("error:create thread failed!!\n");exit(0);}i++;}//destroy threadwhile(i < 5){pthread_join(philosopher[i], NULL);i++;}i = 0;//destroy semwhile(i < 5){sem_destroy(&chopstic[i]);i++;}return 0;}七、实验及结果分析:运行结果:udbwxfso@ubuntu:~/Desktop/sy2$ gcc gphilosopher.c -pthread udbwxfso@ubuntu:~/Desktop/sy2$ ./a.outphilosopher4 get 4philosopher4 get 0waitting:philosopher0 philosopher1 philosopher2 philosopher3 eating:philosopher4philosopher2 get 2philosopher2 get 3waitting:philosopher0 philosopher1 philosopher3eating:philosopher2 philosopher4philosopher4 put 4philosopher4 put 0philosopher4 get 4philosopher4 get 0waitting:philosopher0 philosopher1 philosopher3eating:philosopher2 philosopher4philosopher2 put 2philosopher2 put 3philosopher2 get 2philosopher2 get 3waitting:philosopher0 philosopher1 philosopher3eating:philosopher2 philosopher4philosopher4 put 4philosopher3 get 4philosopher4 put 0philosopher0 get 0philosopher0 get 1waitting:philosopher1 philosopher3 philosopher4eating:philosopher0 philosopher2philosopher2 put 2philosopher2 put 3philosopher2 get 2philosopher2 get 3waitting:philosopher1 philosopher3 philosopher4eating:philosopher0 philosopher2philosopher2 put 2philosopher2 put 3philosopher2 get 2philosopher2 get 3waitting:philosopher1 philosopher3 philosopher4eating:philosopher0 philosopher2经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥使用,用一个信号量表示一只筷子,由这五个信号量组成信号量数组。

若哲学家饥饿时总是先拿其左边的筷子,成功后,再去拿右边的筷子,容易造成死锁。

当规定奇数号哲学家先拿起右边筷子,然后再去拿左边筷子,而偶数号哲学家则相反后,死锁现象得到了解决。

八、实验结论、心得体会和改进建议:通过这次操作系统的实验,我了解到了进程的创建及进行,明白了死锁产生的原因和一些解决的办法,这让我深刻的体会到操作系统的知识作用。

而且此次实验还培养了我综合运用知识的能力,结合了C语言的知识来解决这个问题。

相关文档
最新文档