哲学家就餐问题

合集下载

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

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

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

哲学家进餐问题是一个经典的计算机科学问题,用来展示并发编程中可能出现

的资源竞争和死锁问题。这个问题的描述是:五位哲学家围坐在一张圆桌前,每位哲学家面前有一碗意面,但他们之间共享一把只能被一个人同时使用的餐叉。每位哲学家需要先拿起右手边的餐叉,再拿起左手边的餐叉才能吃饭,吃完后放下餐叉继续思考问题。如果哲学家之间同时试图拿起自己左右手边的餐叉,就会导致死锁问题,无法继续进餐。

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

和死锁问题。实际上,哲学家进餐问题也可以被看作是对资源管理和同步机制的一种考验。如果每位哲学家都按照固定的顺序拿餐叉,就不会发生死锁;而如果哲学家们都随机地尝试拿餐叉,就可能会出现资源竞争的问题,导致无法进餐。

这个问题的趣味之处在于,通过一个简单的场景,展示了复杂的并发编程中可

能出现的问题,让人们更加深入地理解并发编程中的挑战和技巧。通过哲学家进餐问题的讨论,人们可以思考如何设计合理的同步机制和资源管理策略,避免竞争和死锁问题的发生,提高程序的并发性能和稳定性。

总的来说,哲学家进餐问题是一个充满趣味和启发的例子,能够帮助人们更好

地理解并发编程中的难点,同时也能够激发人们对于解决问题的创造力和思考能力。通过这个例子的讨论,人们可以不仅仅学到技术知识,更能够培养出解决问题的能力和思维方式,为未来的学习和工作打下坚实的基础。愿每位哲学家都能够顺利进餐,思考问题,探索未知的世界。

操作系统课程设计——哲学家进餐问题

操作系统课程设计——哲学家进餐问题

操作系统课程设计——哲学家进餐问题1000字

哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着

广泛的应用。因此,在操作系统课程设计中,探究哲学家进餐问题

是一件非常有意义的事情。

哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲

学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。

每个哲学家有两种状态:思考和进餐。当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这

两只筷子,进入思考状态。

在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会

出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法

拿到右手边的筷子,导致无法进餐。因此,需要在代码中实现同步

互斥机制,避免死锁的发生。

本课程设计中,我使用了Java语言来实现哲学家进餐问题。在代码

实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来

模拟哲学家的思考和进餐过程。为了避免死锁,我使用了

Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果

取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的

筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等

待下一个机会。

在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。每个筷子都是一个二元信号量,初始为1,表示可用。当一个哲学

家拿起筷子时,他会将对应的信号量减1,表示不可用。当哲学家

用完筷子之后,会将对应的信号量加1,表示可用。通过这种方式,实现了对筷子的访问同步。

哲学家进餐问题

哲学家进餐问题

哲学家进餐问题

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,当他们试图去拿右手边的筷子时,都将无筷子而陷入无限期的等待。

哲学家进餐问题

哲学家进餐问题

pa() */
哲学家进餐问题
潘晓荷
计科41
1924130
பைடு நூலகம்
在哲学家进餐问题中, 较难解决的是可能出 现的死锁问题:如当 五位哲学家同时饥饿 而各自拿起左边的筷 子时,就会使五个信 号量fork均为0;当他 们再试图去拿右边的 筷子时,都将因无筷 子可拿而无限期地等 待。该如何解决呢?
解决方案: 解决方案:
解决方案一:至多只允许四位哲学家同时去拿左边的
筷子。
Program dining-philosophers; Var fork:array[0..4] of semaphore(:=1); room :semaphore (:=4); i: integer; Procedure philosopher (i: integer); begin repeat think; /*哲学家正在思考*/ wait(room);/*第5位哲学家将被阻塞 在room信号队列*/ wait( fork [i]); /*取其左边的筷 子*/ wait(fork[i+1]mod 5); /*取其右边的筷 子*/ eat; signal(fork[i+1]mod 5); signal (fork [i]); signal (room); forever; end; begin par-begin philosopher(0); philosopher(1); philosopher(2); philosopher(3); philosopher(4); par-end end.

哲学家进餐问题-3中解决方案

哲学家进餐问题-3中解决方案

哲学家进餐问题-3中解决⽅案

问题描述

⼀张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆⼀根筷⼦,桌⼦的中间是⼀碗⽶饭,如图2-10所⽰。哲学家们倾注毕⽣精⼒⽤于思考和进餐,哲学家在思考时,并不影响他⼈。只有当哲学家饥饿的时候,才试图拿起左、右两根筷⼦(⼀根⼀根地拿起)。如果筷⼦已在他⼈⼿上,则需等待。饥饿的哲学家只有同时拿到了两根筷⼦才可以开始进餐,当进餐完毕后,放下筷⼦继续思考。

问题分析

1) 关系分析。5名哲学家与左右邻居对其中间筷⼦的访问是互斥关系。

2) 整理思路。显然这⾥有五个进程。本题的关键是如何让⼀个哲学家拿到左右两个筷⼦⽽不造成死锁或者饥饿现象。那么解决⽅法有两个,⼀个是让他们同时拿两个筷⼦;⼆是对每个哲学家的动作制定规则,避免饥饿或者死锁现象的发⽣。

⼀共5个哲学家,编号0 ~4, 5⽀筷⼦编号也是0 ~4, 0号哲学家右⼿的筷⼦编号是0号,逆时针增加,哲学家的编号也是逆时针增加所以:

0号哲学家对应的是: 4号和1号筷⼦.

1号哲学家对应的是: 0号和2号筷⼦.

2号哲学家对应的是: 1号和3号筷⼦.

3号哲学家对应的是: 2号和4号筷⼦.

4号哲学家对应的是: 3号和0号筷⼦.

所以有宏定义:

#define left(phi_id) (phi_id+N-1)%N

#define right(phi_id) (phi_id+1)%N

N = 5

5⽀筷⼦对应5个互斥锁,所以:

pthread_mutex_t forks[N]={PTHREAD_MUTEX_INITIALIZER};

哲学家线程需要执⾏的动作是:

哲学家用餐问题

哲学家用餐问题

Fra Baidu bibliotek
选做题:
• 根据以前做过的实验,把算法移植到给定的图形用户界 面(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); }

哲学家实验报告

哲学家实验报告

哲学家实验报告

1. 引言

本报告旨在介绍和讨论著名的哲学家就餐问题,该问题描述了一组哲学家在共

享一张圆桌时遇到的资源竞争和死锁问题。在实验中,我们将探讨不同的解决方案以及它们的有效性和局限性。

2. 实验背景

在哲学家就餐问题中,有五个哲学家坐在一张圆桌周围,并且每个哲学家面前

都有一盘面条和一只叉子。这些哲学家在思考时会感到饥饿,因此需要进食。然而,该圆桌上只有五只叉子供他们共享使用。每个哲学家必须同时持有左右两只叉子才能进食。由于叉子限制,哲学家们可能会遇到资源竞争导致饥饿和死锁的问题。

我们将利用计算机模拟该问题,并通过编写程序来探索不同的解决方案。

3. 实验步骤

3.1 单纯实现

在一开始的实验中,我们将使用简单的算法来模拟哲学家就餐问题。我们假设

哲学家们按照顺序获取叉子,并按照相同的顺序放下叉子。然而,这种实现方式容易导致死锁情况的发生。

3.2 解决死锁问题

为了解决死锁问题,我们可以引入等级制度来确保哲学家们按照一定的顺序获

取叉子。例如,我们可以规定每个哲学家只有在左右两边的叉子都可用时才可以进食。这样,哲学家们将会按照固定的顺序获取叉子,从而避免死锁的发生。

3.3 引入资源管理者

为了更好地管理叉子的使用,我们可以引入一个资源管理者来控制叉子的获取

和释放。资源管理者可以通过为每个叉子分配一个状态(被使用或空闲)来跟踪叉子的情况。哲学家将需要向资源管理者请求获取叉子,如果叉子不可用,则将会阻塞直到叉子可用。

3.4 优化方案

除了上述解决方案,还有其他一些优化方案可以被采用。例如,可以引入超时

哲学家进餐问题

哲学家进餐问题

哲学家进餐问题

5 个不讲卫生的哲学家围绕一张圆桌而坐,桌子上放着5 支筷子,每两个哲学家之

间放一支;哲学家的动作包括思考和进餐,进餐时需要同时拿起他左边和右边的两支筷子,思考时则同时将两支筷子放回原处。

解法一:

semaphore Fork[4]={0,1,2,3,4};

philosopher_i()

{

Thinking;

Being hungry;

P(Fork[i mod 5]);

P(Fork[(i + 1) mod 5]);

Eating;

V(Fork[i mod 5]);

V(Fork[(i + 1) mod 5]);

}

这种解法存在问题,会导致死锁,假如5 个哲学家同时饥饿而各自拿左边的筷子时,

会导致5 个筷子的信号量均为0,当他们试图拿右边的筷子时,都将因没有筷子而无限

等待。对于这种死锁问题,可以采用以下几种解决方法:

1)仅当哲学家的左右筷子均可用时,才允许其进餐。(即用AND 信号量机制解决)

解法如下:

Semaphore array[5]={1,1,1,1,1};

Philosopher_i() //i=0,1,2,3,4

{

While(ture)

{

Think;

Sswait(chopstick[(i+1)mod5],chopstick[i]);

Eat;

Ssignal(chopstick[(i+1)mod5],chopstick[i]);

}

}

2)规定奇数号哲学家先拿左边筷子,然后拿右边筷子;而偶数号哲学家相反。解法如下:

semaphore c[5]={1,1,1,1,1}; 初值均为1;

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

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

哲学家就餐问题是计算机科学中一个经典的同步问题,它描述了五位

哲学家围坐在圆桌前就餐,每位哲学家必须先拿起右边的餐具再拿起

左边的餐具,但每次只能有一位哲学家拿起餐具就餐。这个问题的关

键在于如何避免死锁,即所有哲学家都拿起了右边的餐具,然后等待

拿左边餐具的哲学家放下右边的餐具。为了解决这个问题,计算机科

学家提出了三种思路。

第一种思路是引入一个“服务生”,服务生负责给哲学家提供餐具,

每次只允许一个哲学家向服务生请求餐具,这样就可以避免死锁。然而,这种方法可能会引入新的竞争条件,服务生可能会成为新的瓶颈,从而降低系统的效率。

第二种思路是引入资源分级,为了避免死锁,可以给每个哲学家的餐

具加上编号,要求哲学家先拿编号较小的餐具,再拿编号较大的餐具。这样就可以避免死锁,但是可能会增加系统的复杂性,需要管理更多

的资源状态。

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

件分别是互斥、请求并持有、不可剥夺和循环等待。为了避免死锁,

可以破坏其中一个或多个条件。可以引入超时机制,当哲学家拿到一

个餐具后,一定时间内没有获得另一个餐具,就放下手中的餐具,避

免形成循环等待。这种方法可以在不增加系统复杂性的情况下有效地

解决死锁问题。

在我看来,这三种思路各有优缺点,要根据具体的场景和需求选择合适的方法。不同的问题可能需要采用不同的思路来解决,需要权衡各种因素来做出最佳的决策。

哲学家就餐问题是一个充满哲学思考的经典问题,它不仅考察了计算机科学中的同步与互斥问题,更可以引发我们对于资源分配、竞争条件和系统设计的深入思考。通过对哲学家就餐问题的深入理解,我们可以更加灵活地运用不同的思路解决实际中的问题,让我们的系统更加健壮和高效。

操作系统实验报告哲学家就餐

操作系统实验报告哲学家就餐

操作系统实验报告哲学家就餐

一、实验目的:

通过模拟哲学家就餐问题,了解并掌握操作系统中的进程同步机制,以及解决进程间资源竞争所引发的死锁问题。

二、实验介绍:

哲学家就餐问题是由荷兰计算机科学家伊克斯特拉(Dijkstra)于1965年首次提出的。其问题描述如下:

五位哲学家坐在一张圆桌子周围,每个哲学家面前有一碗饭和一根筷子。哲学家的生活方式是交替地进行思考和进食。

当一个哲学家思考时,他不需要使用他的两个筷子;当一个哲学家想吃饭时,他需要同时获取他的左右两个筷子,并在获取到筷子后才能开始进食。

问题的关键是如何解决哲学家间的筷子竞争问题,以及避免死锁的发生。

三、实验设计:

1.并发思路

每个哲学家作为一个进程,在进行思考和进食这两个操作之前,需要获取他的两个筷子。

接下来考虑进程同步的两个关键点:

-互斥:保证每个筷子同时只能被一个哲学家使用,避免资源竞争问题。

-死锁避免:通过限制只允许至多四位哲学家同时持有筷子,从而避

免死锁发生。

2.进程同步机制

- 互斥:使用Semaphore实现互斥,每个筷子都是一个Semaphore,

初始值为1

-死锁避免:引入一个全局计数器,记录当前持有筷子的哲学家数量,每次哲学家想要获取筷子时,先检查该计数器,仅当计数器小于4时才会

获取筷子。

四、实验步骤:

1.创建5个哲学家进程和5个筷子线程。

2.每个哲学家的线程循环执行思考和进食操作。

3.在进食之前,哲学家需要获取两个筷子,获取筷子的顺序按照哲学

家编号进行,每个哲学家先获取自己的左边筷子,再获取自己的右边筷子。

4.进行进食操作后,哲学家释放两个筷子。

哲学家就餐问题

哲学家就餐问题

哲学家就餐问题

实验⼀

⼀、实验名称:哲学家就餐问题的实现

⼆、实验学时: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. 程序代码(重要代码请注释)

哲学家进餐问题

哲学家进餐问题

THANKS FOR WATCHING
感谢您的观看
05
问题的发展和未来方向
问题的发展
起源
哲学家进餐问题起源于计算机科学和数学的交叉领域,旨在解决并 发控制和死锁问题。
经典模型
经典的哲学家进餐问题模型包括五个哲学家围坐在圆桌旁,只有两 个相邻的哲学家可以拿起叉子,目标是让所有哲学家都能进餐。
扩展模型
随着研究的深入,哲学家进餐问题模型不断扩展,包括多叉子版本、 带死锁检测版本等。
未来的研究方向
并发控制
未来的研究可以继续深入探索并发控制策略,以解决哲学家进餐 问题中的死锁和饥饿问题。
人工智能应用
随着人工智能技术的发展,哲学家进餐问题可以应用于多智能体 系统中的协调和控制问题。
扩展模型研究
未来可以对扩展的哲学家进餐问题模型进行深入研究,如多叉子 版本、带死锁检测版本等。
对未来的影响和预测
详细描述
资源分级算法将哲学家和筷子都视为资源,并根据其重要性 进行分级。在分配资源时,优先满足更高级别的资源请求。 这样可以确保每个哲学家都能获得所需的资源,避免出现循 环等待的情况,从而避免死锁的发生。
算法三:超时和重试机制
总结词
超时和重试机制通过限制等待时间和重试次数来避免死锁的发生。
详细描述
并发控制领域
哲学家进餐问题将继续在并发控制领域发挥重要作用,为解决并 发控制和死锁问题提供理论支持和实践指导。

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

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

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

在哲学家就餐问题中,假定有五位哲学家围坐在一张圆桌旁,每位哲学家面前

都放着一碗意面和一把叉子。这五位哲学家中的每位都有两种活动,一种是思考,一种是就餐。但是,这五位哲学家只有五支叉子共用,也就是说,每个哲学家只能在自己左右两边分别拿起一把叉子。若这五位哲学家中有若干人同时拿着左手边的叉子,或者同时拿着右手边的叉子,那么他们都无法就餐。这时,就需要找到一种算法来解决这个问题。

解法一:Chandy/Misra解法

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

的人要叉子。一旦它们都拿到了右边的叉子,就会开始就餐,然后把左右两个叉子都放回去。这种算法的优点是它具有分布式系统的特点,不会造成资源竞争,而且在算法处理结束后,所有人都不会处于饥饿状态。但是,这种算法实现的难度比较大,因为需要每个哲学家都向右边的人要叉子,而且需要考虑异常情况。

解法二:Dijkstra解法

Dijkstra解法也被称为银行家算法,它的思路是让每一位哲学家先拿一支叉子,只有拿到两支叉子后,才可以开始就餐。一旦就餐结束,哲学家就将叉子放回去。这种算法的优点是它比较简单,易于实现。但是,如果有一位哲学家先拿了一支叉子并且不再释放,那么其他哲学家就会陷入死锁状态。

解法三:Semaphore解法

Semaphore解法是以信号量为基础的算法,它的思路是对每支叉子定义一个信

号量,并使用信号量来控制哲学家与叉子之间的关系。一旦一个哲学家想要就餐,就需要请求两个叉子的信号量,如果请求不到,则会被阻塞。这种算法的优点是它具有可扩展性,而且可以支持多个进程同时使用资源。但是,它比较复杂,可能会导致死锁。

操作系统-哲学家就餐问题

操作系统-哲学家就餐问题

一、问题描述:

有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人

之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃通心粉.为了吃通心粉,每

个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子

二、防止死锁发生的分配方式:

仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子。这样要么一次占有两只筷子(所有线程需要的资源)进行下一步的吃通心粉,然后释放所有的资源;要么不占用资源,这样就不可能产生死锁了。

三、产生死锁的分配方式:

当筷子(资源)可用时,先分配左边的筷子,等待一会后再分配右边的筷子,由于这个过程中,左边的筷子一直没有释放,就有可能产生死锁了。

四、程序运行说明

程序运行过程中会弹出一个MessageBox提示操作者操作:

1.第一个对话框用于选择运行模式

a.选择yes 表示采用的是运行的防止死锁的方式,这样的话整个程序可以一直运行下去,不会产生死锁。

b.选择no 表示运行产生死锁的方式会弹出第二个对话框。

2.第二个对话框用于选择运行时,线程运行的时间

a. 选择 res 线程时间比较短,很快就可以死锁

b.选择no 线程时间跟选择yes 时候的时间差不多,产生死锁的时间稍微长一点

五、关于哲学家就餐问题的程序代码分析:

A. Dining.c

变量说明:

函数说明:

B.Mutex.c

函数说明:

1. DWORD WINAPI PhilosopherThread(LPVOID pVoid)

哲学家进程:

用于分配给哲学家筷子(资源)通过开始运行时候的对话框的选择来控制资源的分配方式:两中分配方式见二、三所述。通过随机产生的时间来控制线程的运行,每个哲学家的状态都是resting waiting eating,一直循环。

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

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

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

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

一、引言

哲学家就餐问题是计算机科学中一个经典的并发算法问题,其旨在通

过模拟哲学家进餐的过程来展示并发编程中可能出现的死锁情况及解

决方法。在这个问题中,有五个哲学家坐在一张圆形桌子周围,每个

哲学家有自己的饭碗和叉子。他们的生活习惯是交替思考和进餐:当

一个哲学家思考时,他将放下叉子,尝试从左右两边的邻居那里得到

两个叉子以进行用餐;当一个哲学家吃饭时,他会用完两个叉子,然

后放下叉子并继续思考。问题的关键是如何避免哲学家之间发生死锁,即每个哲学家都拿起了自己右边的叉子,而没有一个人能拿到他左边

的叉子。本文将介绍三种解决死锁问题的思路。

二、解决思路一:资源分级

资源分级的思路是将叉子进行分级,例如将五个叉子从1到5进行编号。对于每个哲学家,他必须先尝试获得数字较小的叉子,然后才能

尝试获取数字较大的叉子。这样做的目的是避免所有哲学家同时尝试

获取同一个叉子,从而导致死锁的发生。当一个哲学家需要进餐时,

他必须先获取编号较小的叉子,然后尝试获取编号较大的叉子。如果他无法获取到编号较小的叉子,他就会放下已经获取的叉子,并释放已经占用的资源。这样,其他哲学家就有机会获取叉子继续进餐。这种思路可以有效地解决死锁问题。

三、解决思路二:资源分配顺序

资源分配顺序的思路是约定哲学家获取叉子的顺序。在这种思路中,我们可以为每个哲学家分配一个固定的顺序,例如从1到5。按照这个顺序,哲学家们必须按照排列顺序尝试获取叉子。当一个哲学家需要进餐时,他会按照规定的顺序尝试获取叉子。如果他无法获取到所需的叉子,他就会放下已经获取的叉子,并释放已经占用的资源。这样,其他哲学家就有机会获取叉子继续进餐。通过约定获取资源的顺序,我们可以避免死锁的发生。

哲学家进餐问题

哲学家进餐问题
B.原理:仅当哲学家的左右两支筷子都可用时, 才允许他拿起筷子进餐。
8
哲学家进餐问题的应用
操作系统线程同步 生Hale Waihona Puke Baidu中人行马路同步
9
感谢您的阅读收藏,谢谢!
7
解决问题的办法
A.原理:至多只允许四个哲学家同时进餐,以保 证至少有一个哲学家能够进餐,最终总会释放出他 所使用过的两支筷子,从而可使更多的哲学家进餐。 以下将room 作为信号量,只允许4 个哲学家同时 进入餐厅就餐,这样就能保证至少有一个哲学家 可以就餐,而申请进入餐厅的哲学家进入room 的 等待队列,根据FIFO 的原则,总会进入到餐厅就 餐,因此不会出现饿死和死锁的现象。
5
以上两个问题反映的是程序并发执行时进 程同步的两个关键问题:饥饿和死锁。为 了提高系统的处理能力和机器的利用率, 并发程序被广泛地使用,因此,必须彻底 解决并发程序执行中的死锁和饥饿问题。
6
于是,哲学家问题推广为更一般性的n个进 程和m个共享资源的问题,并在研究过程中 给出了解决这类的问题的不少方法和工具, 如Pertri网、并发程序设计语言等。
如何协调5位置学家的生活进程,使得每位 哲学家最终都可以进餐?
4
考虑下面的两种情况。
(1)哲学家的生活进程,当所有的哲学家都同时 拿起左手筷子时,则所有哲学家都将拿不到右手 筷子,并处于等待状态,那么,哲学家都将无法 进餐,最终饿死。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
“进餐”->“思考”:此状态改变发生后,哲学家放下左右手上的筷子。筷子状态由“使用中”转变为“空闲”。
“思考”->“等待”:哲学家思考结束后,无条件转入等待状态。
由上所述,程序中应设置5个元素的信号量数组,chopsticks[5],用来保持哲学家之间的同步。
2.2
不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。每个进程中访问临界资源的那段代码称为临界区(Critical Section)。
Philosopher
-number:int
-status:int
+Philosopher(innum:int)
+find() const:int
+getinfo() const:int
+Change():void
图4-1哲学家类的UML图
Number对象:哲学家的编号。
Status对象:用于保存当前该哲学家的状态,0表示正在等待(即处于饥饿状态)1表示得到餐具正在吃饭,2表示正在思考
数学与计算机学院
课程设计说明书
课 程 名 称:操作系统原理-课程设计
课 程 代 码:8404061
题 目:哲学家就餐问题模拟
年级/专业/班:09级信息与计算科学三班
学 生 姓 名:徐磊
学 号:312009070102301
开 始 时 间:2012年05月14日
完 成 时 间:2012年05月31日
课程设计成绩:
chopsticks[number%5]=false;//拿起左边的筷子
chopsticks[(number+1)%5]=false;//拿起右边的筷子
status=1;
}
}
LeaveCriticalSection (&cs) ;//释放临界区
}
string print(Philosopher *pA)//返回哲学家状态
}
voidChange() ;//状态改变函数
};
voidPhilosopher::Change()
{
EnterCriticalSection (&cs) ;//进入临界区
if(status==1)//正在进餐
{
chopsticks[(number)%5]=true;//放下左手工具
chopsticks[(number+1)%5]=true;//放下右手工具
boolchopsticks[5];//全局变量,用餐工具
CRITICAL_SECTION cs;//信号量,在线程中使用,临界区
classPhilosopher
{
private:
intnumber;
intstatus;/*标记当前哲学家的状态,0表示正在等待(即处于饥饿状态),1表示得到两支筷子正在吃饭,2表示正在思考*/
{
//pA->Change();
inti=pA->getinfo();
string str;
if(i==0)
str="等待";
elseif(i==1)
str="就餐";
elsestr="思考";
returnstr;
}
string chopstickstatus(boola)//返回筷子状态
{
string state;
P5.Change();
//P6.Change();
cout<<"当前状态为:"<<endl;
cout<<P1.find()<<print(&P1)<<""<<chopstickstatus(chopsticks[1])<<""<<chopstickstatus(chopsticks[2])<<""<<P2.find()<<print(&P2)<<endl;
Philosopher(intnum)方法:哲学家类构造函数,参数num表示哲学家编号
find() const方法:返回该哲学家编号
getinfo() const方法:返回哲学家当前状态
Change()方法:根据题目要求改变哲学家的状态(等待->进餐->思考->等待…………)
另外,程序中包含一个公有对象,bool类型数组chopsticks[5],用来保存5只筷子当前状态:true表示该餐具当前空闲,false表示该餐具当前正被使用。
学习态度及平时成绩(30)
技术水平与实际能力(20)
创新(5)
说明书撰写质量(45)
总 分(100)
指导教师签名:年月日
1
1.1
哲学家进餐问题也是一个经典的同步问题,它是由Dijkstra提出并解决的。哲学家进餐问题是这样的:5个哲学家以思考、吃饭交替进行的方式生活,他们共享一张周围有5把椅子的圆桌,每人一把椅子,在桌子上摆有5个饭碗和5只筷子。当一个哲学家思考时,他不与邻座同事发生联系。当一哲学家饿了,他就试图拿起他左右两边的筷子吃饭。显然,他不能拿起已抓在他的邻座手中的筷子,于是,他可能只拿到一只甚至一只筷子也拿不到。当一个饥饿的哲学家得到了两只筷子,他就可以吃饭。当他用饭毕,就放下筷子并再次开始思考。5个哲学家共享5支筷子,最多只能不相邻的两个哲学家同时就餐。
cout<<"--------------------------"<<endl;
cout<<"哲学家们开始生活:"<<endl;
cout<<endl;
cout<<endl;
while(con=='y')
{
P1.Change();
P2.Change();
P3.Change();
P4.Change();
return0;
}
public:
Philosopher(intnum=1): status(2), number(num) { }
intfind()//定义常成员函数返回该哲学家编号
const
{
returnnumber;
}
intgetinfo()//定义常成员函数返回哲学家当前状态
const
{
returnstatus;
EnterCriticalSection (&cs)用来进入临界区,LeaveCriticalSection (&cs)用来离开临界区。
3 程序运行平台
Visual Studio 2008。
具体操作如下:新建项目,添加相应的源文件,再编译,链接,执行等。
4
程序中定义一个哲学家类,包含两个私有对象和四个公有对象。
6
首先进入Visual Studio 2008,进入源程序。生成称解决方案,然后运行。
图6-1哲学家开始状态1
图6-2哲学家状态2
图6-3哲学家状态3
图6-4哲学家状态4
8结论
对自己完成的题目进行总结,包括程序的功能、创新点(与众不同的地方)及程序存在的问题和修改对策。
通过本次课程设计的过程,我了解了金典的同步问题哲学家就餐问题。发现自己对互斥变量把握不太清楚。及在编程过程中自己对C++语法的不熟悉。
在多道程序设计环境下,进程同步问题十分重要,其中“哲学家进餐问题”是较有代表性的。通过对该问题的研究学习和实践,可以帮助我们更好的理解和掌握临界资源、进程同步的概念和实现方法。
1.2
本课题主要的目的通过实现哲学家进餐问题的同步深入了解和掌握进程同步和互斥的原理。
2.
2.1
哲学家的生活就是思考和吃饭,即思考,饿了就餐,再思考,循环往复。要求是:每一个哲学家只有在拿到位于他左右筷子,才能够就餐;哲学家只能先拿一只筷子,再去拿另一只筷子,而不能同时去抓他旁边的两只筷子,也不能从其他哲学家手中抢夺筷子;哲学家每次就餐后必须放下他手中的两只筷子后恢复思考,不能强抓住筷子不放。
InitializeCriticalSection (&cs) ;//初始化初始化临界区
cout<<"-----------------------状态说明示意图:-----------------------"<<endl;
cout<<"哲学家号的状态"<<""<<"筷子的状态"<<""<<"筷子的状态"<<""<<"哲学家号的状态"<<endl;
cout<<""<<P5.find()<<print(&P5)<<""<<endl;
cout<<"--------------------------"<<endl;
cout<<"若要继续下一状态,输入y;输入其他,结束程序:";
cin>>con;
Sleep(20);
}
DeleteCriticalSection (&cs) ;//退出资源区
每个进程中访问临界资源的那段程序称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
本程序主要使用了EnterCriticalSection (&cs)和LeaveCriticalSection (&cs)两个函数实现临界区互斥。
设计一个程序,能够显示当前各哲学家的状态和桌上餐具的使用情况,并能无死锁的推算出下一状态各哲学家的状态和筷子的使用情况。即设计一个能安排哲学家正常生活的程序。
为哲学家设计3种状态,即“等待”“进餐”“思考”。每个哲学家重复进行“等待”->“进餐”->“思考”的行动循环。其中:
“等待”->“进餐”:只有一个哲学家处于等待进餐状态,且左右手两边的筷子都处于“空闲”ห้องสมุดไป่ตู้态时,可以发生这种状态改变。此状态改变发生后,哲学家拿起左右手两边的筷子。
status=2;//改变状态为思考
}
elseif(status==2)//思考中
{
status=0;//改变状态为等待
}
elseif(status==0)//等待中
{
if(chopsticks[number%5]&&chopsticks[(number+1)%5])//左右手两边筷子均为空闲状态
{
本程序通过定义一个哲学家类,模拟了哲学家就餐,思考和等待的不同状态。
附 录
附录1 源程序清单
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<string>
#include<iostream>
usingnamespacestd;
if(a==true)
state="闲";
if(a==false)
state="用";
returnstate;
}
intmain()
{
charcon ='y';//判断是否继续
for(inti=1;i<=5;i++)
chopsticks[i]=true;//5根筷子都未使用,初始化
Philosopher P1(1),P2(2),P3(3),P4(4),P5(5);
cout<<""<<chopstickstatus(chopsticks[5])<<""<<endl;
cout<<P3.find()<<print(&P3)<<""<<chopstickstatus(chopsticks[3])<<""<<chopstickstatus(chopsticks[4])<<""<<P4.find()<<print(&P4)<<endl;
cout<<""<<"筷子的状态"<<endl;
cout<<"哲学家号的状态"<<""<<"筷子的状态"<<""<<"筷子的状态"<<""<<"哲学家号的状态"<<endl;
cout<<""<<"哲学家号的状态"<<""<<endl;
cout<<"筷子的状态,“用”表示使用中,“闲”表示空闲中。"<<endl;
程序中还包含两个公有函数:print和chopstickstatus。Print用来返回一个哲学家的状态,chopstickstatus用来返回一个餐具的状态。
5
5
图5-1主程序模块流程图
5
图5-2状态改变模块Change()流程图
5
图5-3返回哲学家状态模块print()流程图
5
图5- 4返回餐具状态模块chopsticksstatus(bool a)流程图
相关文档
最新文档