操作系统课程设计_哲学家进餐问题
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 5
0 ms: O O O O O
95 ms: ! O O O O
95 ms: X O O O O
214 ms: X O O O !
327 ms: X O O ! !
操作系统课程设计——哲学家进餐问题
操作系统课程设计——哲学家进餐问题1000字
哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着
广泛的应用。因此,在操作系统课程设计中,探究哲学家进餐问题
是一件非常有意义的事情。
哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲
学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。
每个哲学家有两种状态:思考和进餐。当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这
两只筷子,进入思考状态。
在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会
出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法
拿到右手边的筷子,导致无法进餐。因此,需要在代码中实现同步
互斥机制,避免死锁的发生。
本课程设计中,我使用了Java语言来实现哲学家进餐问题。在代码
实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来
模拟哲学家的思考和进餐过程。为了避免死锁,我使用了
Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果
取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的
筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等
待下一个机会。
在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。每个筷子都是一个二元信号量,初始为1,表示可用。当一个哲学
家拿起筷子时,他会将对应的信号量减1,表示不可用。当哲学家
用完筷子之后,会将对应的信号量加1,表示可用。通过这种方式,实现了对筷子的访问同步。
操作系统哲学家进餐问题
操作系统实习
报告
一、设计目的:
死锁是进程并发执行过程中可能出现的现象,所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局。哲学家就餐问题是描述死锁的经典例子。为了防止死锁,可以采用资源预分配法或者资源按序分配法。资源预分配法是指进程在运行前一次性地向系统申请它所需要的全部资源,如果系统当前不能够满足进程的全部资源请求,则不分配资源, 此进程暂不投入运行,如果系统当前能够满足进程的全部资源请求, 则一次性地将所申请的资源全部分配给申请进程。
二、设计内容
哲学家进餐问题的模拟。
三、开发环境
windows环境,Myeclipse平台。
四、分析设计
<一>实验原理
哲学家进餐问题描述的是五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五只碗和五只筷子。他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右的最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕放下筷子继续思考。
由于:①只有拿到两只筷子时,哲学家才能吃饭;②如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;③任何一个哲学家在自己
没有拿到两只筷子吃饭之前,决不放下自己手中的筷子。则可能出现五个哲学家都饥饿时都拿着一直筷子。这样就可能五个哲学家都用不上餐。
该问题可用记录型信号量解决,经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥使用,可以用一个信号量表示一只筷子,由这五个信号量组成信号量数组。当哲学家饥饿时总是先拿其左边的筷子,成功后,再去拿右边的筷子,又成功后方可就餐。进餐完,又先放下他左边的筷子,再放下右边筷子。这个算法可以保证不会有两个相邻的哲学家同时就餐,但有可能引起死锁。
计算机操作系统哲学家进餐问题的教学探讨
计算机操作系统哲学家进餐问题的教学探讨
计算机操作系统哲学家进餐问题是一个经典的模拟问题,用于帮助学生理解线程同步、死锁和资源管理等操作系统的核心概念。
该问题描述了n个哲学家围坐在一张圆桌周围,每个哲学家面前有一盘食物,中间有n个筷子。哲学家需要吃饭,但是每个哲学家只能使用自己左右两边的筷子来进餐。如果哲学家发现左边或右边的筷子被占用,就会等待,直到筷子被释放。这个问题中存在死锁的可能性。
在教学中,可以通过演示代码或编写代码来模拟这个问题的运行情况,帮助学生理解这些概念的实际应用。例如,可以演示如何使用锁和条件变量来解决死锁问题,或者如何
使用信号量管理系统资源来避免死锁问题。
另外可以讨论不同的算法和策略,如顺序获取筷子,随机获取筷子等,来说明如何避免死锁的发生.
总之,通过这个问题的模拟,学生可以加深对操作系统的理解,并且对如何解决多线程并发问题有更深入的了解。
在教学探讨中,老师可以通过不同的模拟实验来说明线程同步和死锁的本质原理以及如何避免和解决这些问题。鼓励学生进行自己的实验和探究,以加深对这些概念的理解。
操作系统课程设计哲学家就餐问题
目录
摘要 (2)
第一章课程设计的目的及要求 (3)
1.1设计目的 (3)
1.2设计要求 (3)
1.3设计环境 (3)
第二章需求分析 (4)
2.1问题描述: (4)
2.2问题分析: (4)
第三章详细分析 (5)
3.1 问题定义 (5)
3.2算法分析: (5)
3.3 界面设计 (6)
第四章程序部分代码分析 (8)
第五章新得体会 (10)
第六章参考文献 (11)
附录 (11)
摘要
在多道程序环境下,进程同步问题十分重要,也是相当有趣的问题,因而吸引了不少学者对它进行研究,由此而产生一系列经典的进程同步问题.其中较有代表性的是哲学家进餐问题等等,通过这些问题的研究和学习,可以帮助我们列好地理解进程同步概念及实现方法.
由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题,该问题是描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐,平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐,进餐毕,放下筷子继续思考.
由于筷子数目有限,不能让五个哲学家同时进餐,而且甚至只能让其中的少数哲学家进餐,其他的哲学家只能轮流享用,这非常类似多线程之间的同步互斥问题,所以采用windows的多线程及一些API函数实现了对这个经典算法的模拟.
第一章课程设计的目的及要求
1.1设计目的
通过本次课设,对本学期的操作系统课程的学习理论知识的一次应用。是理论结合实际的一次应用。让我们学会对竞争资源的操作,控制,同时锻炼我们的编程水平。
哲学家进餐问题(操作系统)
哲学家进餐问题(操作系统)
哲学家进餐问题(操作系统)
1. 引言
文档概述:
在操作系统领域,哲学家进餐问题是一个经典的并发控制问题。该问题模拟了五位哲学家围坐在一张圆桌旁,每个哲学家面前放置
着一碗面和一只叉子。哲学家在思考和进餐之间切换,但是他们必
须分享叉子来进行进餐。然而,如果每个哲学家都同时拿起右边的
叉子,就会出现死锁的情况。因此,设计一个合理的算法来解决这
个问题是非常重要的。
2. 问题描述
2.1 哲学家和叉子
在该问题中,有五位哲学家分别编号为 P1、P2、P3、P4、P5,以及五只叉子,编号为 F1、F2、F3、F4、F5.每个哲学家在思考时
不会使用叉子,而在进餐时需要使用相邻两只叉子。
2.2 运行过程
哲学家的运行过程根据以下步骤进行:
- 当一个哲学家饿了后,他会尝试获取左边和右边的叉子。
- 如果两只叉子都可用,哲学家就会进餐,并在完成后释放叉子。
- 否则,哲学家需要等待其他哲学家释放叉子。
3. 解决方案
为了解决哲学家进餐问题,我们可以采用以下方法之一:
3.1 资源分级分配算法
该算法将叉子分为左叉子和右叉子,每个哲学家只能同时拿起左叉子和右叉子。通过约定哲学家只能按照一定顺序拿起叉子,可以避免死锁的发生。
3.2 资源分级分配算法的伪代码:
```
acquire_forks(left_fork_id, right_fork_id) {
if (left_fork_id < right_fork_id) {
acquire(left_fork_id);
acquire(right_fork_id);
哲学家进餐问题
哲学家进餐问题
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,当他们试图去拿右手边的筷子时,都将无筷子而陷入无限期的等待。
linuxc语言哲学家进餐---信号量PV方法一
linuxc语⾔哲学家进餐---信号量PV⽅法⼀
1、实验原理
由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共⽤⼀张圆桌,分别坐在周围的五张椅⼦上,在圆桌上有五个碗和五只筷⼦,他们的⽣活⽅式是交替地进⾏思考和进餐。平时,⼀个哲学家进⾏思考,饥饿时便试图取⽤其左右最靠近他的筷⼦,只有在他拿到两只筷⼦时才能进餐。进餐完毕,放下筷⼦继续思考。
2.实验内容:
显⽰出每个哲学家的⼯作状态,如吃饭,思考。连续运⾏30次以上都未出现死锁现象。
3.分析解决⽅案⼀:
现在引⼊问题的关键:这些哲学家很穷,只买得起五根筷⼦。他们坐成⼀圈,两个⼈的中间放⼀根筷⼦。哲学家吃饭的时候必须同时得到左⼿边和右⼿边的筷⼦。如果他⾝边的任何⼀位正在使⽤筷⼦,那他只有等着。所以我们就假设最多只有4民哲学家在进餐这样就能保证没有死锁的情况。
代码如下:
1 #include<unistd.h>
2#define NUM 5
3int ID[NUM]={0,1,2,3,4};
4 sem_t sem_chopsticks[NUM];
5 sem_t sem_eaters;
6int eaters_num=0;//记录已经吃过饭的次数
7
8//初始化信号量函数
9void sem_signal_init(){
10int i;
11for(i=0;i<NUM;i++){
12if(sem_init(&sem_chopsticks[i],0,1)==-1){
不会出现死锁的哲学家进餐问题
不会出现死锁的哲学家
进餐问题
IMB standardization office【IMB 5AB- IMBK 08- IMB 2C】
试利用记录型信号量写出一个不会出现死锁的哲学家进餐问题的算法。
解法1:
设初始值为1的信号量M[I]表示I号筷子被拿(I=1,2,3,4,5)。
哲学家(I):
Begin
ifImod2==1then
{
Wait(M[I]);
Wait(M[I-1mod5]);
Eat;
Signal(M[I-1mod5]);
Signal(M[I]);
}
else
{
Wait(M[I-1mod5]);
Wait(M[I]);
Eat;
Signal(M[I]);
Signal(M[I-1mod5]);
}
End
解法二:
设初始值为1的信号量M[I]表示I号筷子被拿(I=1,2,3,4,5)。
另设初始值为4的信号量Mutex表示同时最多只允许4个哲学家进餐
哲学家(I):
Begin
Wait(Mutex);
Wait(M[I]);
Wait(M[I-1mod5]);
Eat;
Signal(M[I-1mod5]);
Signal(M[I]);
Signal(Mutex);
End
哲学家就餐问题解决死锁的三种思路
哲学家就餐问题是计算机科学中一个经典的同步问题,它描述了五位
哲学家围坐在圆桌前就餐,每位哲学家必须先拿起右边的餐具再拿起
左边的餐具,但每次只能有一位哲学家拿起餐具就餐。这个问题的关
键在于如何避免死锁,即所有哲学家都拿起了右边的餐具,然后等待
拿左边餐具的哲学家放下右边的餐具。为了解决这个问题,计算机科
学家提出了三种思路。
第一种思路是引入一个“服务生”,服务生负责给哲学家提供餐具,
每次只允许一个哲学家向服务生请求餐具,这样就可以避免死锁。然而,这种方法可能会引入新的竞争条件,服务生可能会成为新的瓶颈,从而降低系统的效率。
第二种思路是引入资源分级,为了避免死锁,可以给每个哲学家的餐
具加上编号,要求哲学家先拿编号较小的餐具,再拿编号较大的餐具。这样就可以避免死锁,但是可能会增加系统的复杂性,需要管理更多
的资源状态。
第三种思路是破坏死锁的四个必要条件之一。死锁发生的四个必要条
件分别是互斥、请求并持有、不可剥夺和循环等待。为了避免死锁,
可以破坏其中一个或多个条件。可以引入超时机制,当哲学家拿到一
个餐具后,一定时间内没有获得另一个餐具,就放下手中的餐具,避
免形成循环等待。这种方法可以在不增加系统复杂性的情况下有效地
解决死锁问题。
在我看来,这三种思路各有优缺点,要根据具体的场景和需求选择合适的方法。不同的问题可能需要采用不同的思路来解决,需要权衡各种因素来做出最佳的决策。
哲学家就餐问题是一个充满哲学思考的经典问题,它不仅考察了计算机科学中的同步与互斥问题,更可以引发我们对于资源分配、竞争条件和系统设计的深入思考。通过对哲学家就餐问题的深入理解,我们可以更加灵活地运用不同的思路解决实际中的问题,让我们的系统更加健壮和高效。
操作系统实验报告哲学家就餐
操作系统实验报告哲学家就餐
一、实验目的:
通过模拟哲学家就餐问题,了解并掌握操作系统中的进程同步机制,以及解决进程间资源竞争所引发的死锁问题。
二、实验介绍:
哲学家就餐问题是由荷兰计算机科学家伊克斯特拉(Dijkstra)于1965年首次提出的。其问题描述如下:
五位哲学家坐在一张圆桌子周围,每个哲学家面前有一碗饭和一根筷子。哲学家的生活方式是交替地进行思考和进食。
当一个哲学家思考时,他不需要使用他的两个筷子;当一个哲学家想吃饭时,他需要同时获取他的左右两个筷子,并在获取到筷子后才能开始进食。
问题的关键是如何解决哲学家间的筷子竞争问题,以及避免死锁的发生。
三、实验设计:
1.并发思路
每个哲学家作为一个进程,在进行思考和进食这两个操作之前,需要获取他的两个筷子。
接下来考虑进程同步的两个关键点:
-互斥:保证每个筷子同时只能被一个哲学家使用,避免资源竞争问题。
-死锁避免:通过限制只允许至多四位哲学家同时持有筷子,从而避
免死锁发生。
2.进程同步机制
- 互斥:使用Semaphore实现互斥,每个筷子都是一个Semaphore,
初始值为1
-死锁避免:引入一个全局计数器,记录当前持有筷子的哲学家数量,每次哲学家想要获取筷子时,先检查该计数器,仅当计数器小于4时才会
获取筷子。
四、实验步骤:
1.创建5个哲学家进程和5个筷子线程。
2.每个哲学家的线程循环执行思考和进食操作。
3.在进食之前,哲学家需要获取两个筷子,获取筷子的顺序按照哲学
家编号进行,每个哲学家先获取自己的左边筷子,再获取自己的右边筷子。
4.进行进食操作后,哲学家释放两个筷子。
哲学家进餐问题
利用记录型信号量解决哲学家进餐问题
1.哲学家进餐问题:
(1) 在什么情况下5 个哲学家全部吃不上饭?
考虑两种实现的方式,如下:
A.
算法描述:
void philosopher(int i)
{
while (TRUE) {
think( );
take_fork(i);
take_fork((i+1) % N);
eat( );
put_fork(i);
put_fork((i+1) % N);
}
}
分析:假如所有的哲学家都同时拿起左侧筷子,看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子,如此这般,永远重复。对于这种情况,即所有的程序都在无限期地运行,但是都无法取得任何进展,即出现饥饿,所有哲学家都吃不上饭。
B.
算法描述:
规定在拿到左侧的筷子后,先检查右面的筷子是否可用。如果不可用,则先放下左侧筷子,等一段时间再重复整个过程。
分析:当出现以下情形,在某一个瞬间,所有的哲学家都同时启动这个算法,拿起左侧的筷子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此这样永远重复下去。对于这种情况,所有的程序都在运行,但却无法取得进展,即出现饥饿,所有的哲学家都吃不上饭。
(2) 描述一种没有人饿死(永远拿不到筷子)算法。
考虑了三种实现的方式(A、B、C):
A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释
放出他所使用过的两支筷子,从而可使更多的哲学家进餐。以下将room 作为信号量,只允
许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入
哲学家就餐
计算机信息与工程系
哲学家就餐算法
——操作系统课程设计
一、应用原理
两个或多个进程无限地等待一个事件,而该事件只能由这些等待进程之一来产生,这个现象就被称为死锁。进程在信号量内无穷等待的情况,被称为饥饿。
这个哲学家就餐问题就是模仿进程之间的同步、饥饿、死锁现象。五个哲学家围坐在一个圆桌上,每两个哲学家之间有一支筷子。在哲学家思考一段时间后就会饥饿,然后就想拿起身边的筷子两边各一支。吃完后放下筷子继续思考,形成一个循环。但是如果当两个相邻的哲学家同时想吃饭时,必须有一个哲学家身边只有一支筷子,必须等待其相邻的哲学家吃完后,放下身边的另一支筷子,才能进餐。如果一个哲学家无限期的等待一支筷子,就会被饿死,也就是进程中的饥饿。当他们互相循环等待的时候,就形成了死锁。这其中,哲学家就好像进程,筷子就好像临界资源。
对于饥饿和死锁的问题,我是这么解决的:当哲学家想吃饭时,首先判断是不是两边同时都有筷子,如果都有得话就吃饭,吃完再把两边的筷子都放下;如果只有一边又筷子的话就等待,不吃饭。这样就不会造成饥饿和死锁现象。
否
三、具体程序
1、随即选择一个哲学家吃饭
srand((unsigned)time(0));
j=rand()% 10;
d=j % 5;
这段代码会随机产生一个数字,并处理在0~4之间,使之成为五个哲学家中的一个,srand 函数的功能是,设置新的尾随机数序列的种子。根据时间不同这个随机数会不一样。rand 就是产生这个随机数,用% 10 变成0~9之间的数,再由% 5变成0~4之间数。
2、设置哲学家的状态
操作系统课程设计——哲学家进餐问题
操作系统课程设计报告
院(系):计算机科学学院
专业:计算机科学与技术专业
学生姓名:
题目:模拟仿真"哲学家进餐"问题的解决过程及方法
起讫日期: 2010.6.30----2010.7.11 完成日期: 2010 年 7 月 10 日
目录
1.设计题目与要求 (2)
1.1实验目的 (2)
1.3 初始条件 (2)
2 总体设计思想及相关知识 (3)
2.1总体设计思想 (3)
2.2 临界区互斥编程原理 (3)
2.3开发环境与工具 (4)
3数据结构与模块说明 (4)
3.1 数据结构 (4)
3.2程序各模块流程图 (6)
3.2.1 主程序模块 (6)
3.2.2 状态改变模块 (7)
3.2.3 返回哲学家状态模块 (8)
3.2.4 返回餐具状态模块 (9)
4. 源程序代码 (10)
5. 测试及结果 (15)
6. 课设总结 (17)
参考文献 (18)
1.设计题目与要求
1.1实验目的
通过实现哲学家进餐问题的同步,深入了解和掌握进程同步和互斥的原理。1.2设计要求
哲学家有N个,也定全体到达后开始讨论:在讨论的间隙哲学家进餐,每人进餐时都需使用刀、叉各一把,所有哲学家刀和叉都拿到后才能进餐。哲学家的人数、餐桌上的布置自行设定,实现刀和叉的互斥使用算法的程序实现。
1.3 初始条件
(1)操作系统:windows
(2)程序设计语言:C++
(3)设定圆桌上有六个哲学家,三对刀叉,如下图摆放:
图1-1 哲学家进餐问题设定图
2 总体设计思想及相关知识
2.1总体设计思想
哲学家的生活就是思考和吃饭,即思考,就餐,再思考,往复循环。要求是:每一个哲学家只有在拿到位于他左右的刀叉后,才能够就餐;哲学家只能先拿一把刀或叉,再去拿另一把刀或叉,而不能同时去抓他旁边的两把餐具,也不能从其他哲学家手中抢夺餐具;哲学家每次就餐后必须放下他手中的两把餐具后恢复思考,不能强抓住餐具不放。
4.10经典进程互斥同步问题:哲学家进餐问题
4.10经典进程互斥同步问题:哲学家进餐问题(the dining philosophers problem)
问题描述:(由Dijkstra首先提出并解决)5个哲学家围绕一张圆桌而坐,桌子上放着5支筷子,每两个哲学家之间放一支,
哲学家的动作包括思考和进餐,
进餐时需要同时拿起他左边和右边的两支筷子,
思考时则同时将两支筷子放回原处。
要考虑的问题是如何保证哲学家们的动作有序进行?如:
不出现相邻者同时要求进餐;
不出现有人永远拿不到筷子。
在这里,哲学家的生活规律是:
Repeat
思考;
取fork[i];取fork[(i+1) mod 5];
进食;
放fork[i];放fork[(i+1) mod 5];
Until false;
实现方法:一个信号量表示一根筷子,五个信号量构成信号量数组chop[5],所有信号量初始值为1。第i个哲学家的进餐过程为:
思考问题
P(chop[i]);
P(chop(i+1) mod 5]);
进餐
V(chop[i]);
V(chop[(i+1) mod 5]);
该算法可保证两个相邻的哲学家不能同时进餐,但不能防止五位哲学家同时拿起各自左边的筷子、又试图拿起右边的筷子,这会引起死锁。
这里给出可以防止死锁发生的一种解决方案:
Semaphore fork[5] = {1};
Semaphore room = 4;
Void philospher (int i) {
while (true) {
thinking();
P( room );
P(fork[i]);
P(fork[(i+1) mod 5])
哲学家就餐问题解决死锁的三种思路
哲学家就餐问题解决死锁的三种思路
哲学家就餐问题解决死锁的三种思路
一、引言
哲学家就餐问题是计算机科学中一个经典的并发算法问题,其旨在通
过模拟哲学家进餐的过程来展示并发编程中可能出现的死锁情况及解
决方法。在这个问题中,有五个哲学家坐在一张圆形桌子周围,每个
哲学家有自己的饭碗和叉子。他们的生活习惯是交替思考和进餐:当
一个哲学家思考时,他将放下叉子,尝试从左右两边的邻居那里得到
两个叉子以进行用餐;当一个哲学家吃饭时,他会用完两个叉子,然
后放下叉子并继续思考。问题的关键是如何避免哲学家之间发生死锁,即每个哲学家都拿起了自己右边的叉子,而没有一个人能拿到他左边
的叉子。本文将介绍三种解决死锁问题的思路。
二、解决思路一:资源分级
资源分级的思路是将叉子进行分级,例如将五个叉子从1到5进行编号。对于每个哲学家,他必须先尝试获得数字较小的叉子,然后才能
尝试获取数字较大的叉子。这样做的目的是避免所有哲学家同时尝试
获取同一个叉子,从而导致死锁的发生。当一个哲学家需要进餐时,
他必须先获取编号较小的叉子,然后尝试获取编号较大的叉子。如果他无法获取到编号较小的叉子,他就会放下已经获取的叉子,并释放已经占用的资源。这样,其他哲学家就有机会获取叉子继续进餐。这种思路可以有效地解决死锁问题。
三、解决思路二:资源分配顺序
资源分配顺序的思路是约定哲学家获取叉子的顺序。在这种思路中,我们可以为每个哲学家分配一个固定的顺序,例如从1到5。按照这个顺序,哲学家们必须按照排列顺序尝试获取叉子。当一个哲学家需要进餐时,他会按照规定的顺序尝试获取叉子。如果他无法获取到所需的叉子,他就会放下已经获取的叉子,并释放已经占用的资源。这样,其他哲学家就有机会获取叉子继续进餐。通过约定获取资源的顺序,我们可以避免死锁的发生。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录
1.设计题目与要求 (1)
1.1实验目的与设计要求 (1)
1.2 初始条件 (1)
2 总体设计思想及相关知识 (2)
2.1总体设计思想 (2)
2.2 临界区互斥编程原理 (2)
2.3开发环境与工具 (3)
3数据结构与模块说明 (3)
3.1 数据结构 (3)
3.2程序各模块流程图 (5)
3.2.1 主程序模块 (5)
3.2.2 状态改变模块 (6)
3.2.3 返回哲学家状态模块 (7)
3.2.4 返回餐具状态模块 (8)
4. 源程序代码 (9)
5. 测试及结果 (14)
6. 课设总结 (16)
参考文献 (17)
1.设计题目与要求
1.1实验目的与设计要求
实验目的:通过实现哲学家进餐问题的同步深入了解和掌握进程同步和互斥的原理。
设计要求:哲学家有N个,也定全体到齐后开始讨论:在讨论的间隙哲学家进餐,每人进餐时都需使用刀、叉各一把,所有哲学家刀和叉都拿到后才能进餐。哲学家的人数、餐桌上的布置自行设定,实现刀和叉的互斥使用算法的程序实现。
1.2 初始条件
(1)操作系统:windows
(2)程序设计语言:C++
(3)设定圆桌上有六个哲学家,三对刀叉,如下图摆放:
图1-1 哲学家进餐问题设定图
2 总体设计思想及相关知识
2.1总体设计思想
哲学家的生活就是思考和吃饭,即思考,饿了就餐,再思考,循环往复。要:每一个哲学家只有在拿到位于他左右的刀叉后,才能够就餐;哲学家只能先拿一把刀或叉,再去拿另一把刀或叉,而不能同时去抓他旁边的两把餐具,也不能从其他哲学家手中抢夺餐具;哲学家每次就餐后必须放下他手中的两把餐具后恢复思考,不能强抓住餐具不放。
设计一个程序,能够显示当前各哲学家的状态和桌上餐具的使用情况,并能无死锁的推算出下一状态各哲学家的状态和桌上餐具的使用情况。即设计一个能安排哲学家正常生活的程序。
为哲学家设计3种状态,即“等待”“进餐”“思考”。每个哲学家重复进行“等待”->“进餐”->“思考”的行动循环。其中:
“等待”->“进餐”:只有一个哲学家处于等待进餐状态,且左右手两边的餐具都处于“空闲”状态时,可以发生这种状态改变。此状态改变发生后,哲学家拿起左右手两边的餐具。
“进餐”->“思考”:此状态改变发生后,哲学家放下左右手上的餐具。餐具状态由“使用中”转变为“空闲”。
“思考”->“等待”:哲学家思考结束后,无条件转入等待状态。
由上所述,程序中应设置6个元素的信号量数组,tools[6],用来保持哲学家之间的同步。
2.2 临界区互斥编程原理
不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。每个进程中访问临界资源的那段代码称为临界区(Critical Section)。
每个进程中访问临界资源的那段程序称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
本程序主要使用了EnterCriticalSection (&cs)和LeaveCriticalSection (&cs)两个函数实现临界区互斥。
EnterCriticalSection (&cs)用来进入临界区,LeaveCriticalSection (&cs)用来离开临界区。
2.3开发环境与工具
系统平台:WINDOW环境
实现语言:C++
开发工具:VC++6.0
3数据结构与模块说明
3.1 数据结构
图3-1 哲学家类的UML图
程序中定义一个哲学家类,包含两个私有对象和四个公有对象。
Number对象:报讯哲学家的编号。
Status对象:用于保存当前该哲学家的状态,0表示正在等待(即处于饥饿状态)1表示得到餐具正在吃饭,2表示正在思考
Philosopher(int num)方法:哲学家类构造函数,参数num表示哲学家编号
find() const方法:返回该哲学家编号
getinfo() const方法:返回哲学家当前状态
Change()方法:根据题目要求改变哲学家的状态(等待->进餐->思考->等
待…………)
另外,程序中包含一个公有对象,bool类型数组tools[6],用来保存6把餐当前状态:true表示该餐具当前空闲,false表示该餐具当前正被使用。
程序中还包含两个公有函数:print和toolstatus。Print用来返回一个哲学家的状态,toolstatus用来返回一个餐具的状态。
3.2程序各模块流程图
3.2.1 主程序模块
图3-2 主程序模块流程图
3.2.2 状态改变模块
图3-3 状态改变模块Change()流程图
3.2.3 返回哲学家状态模块
图3-4 返回哲学家状态模块print()流程图
3.2.4 返回餐具状态模块
图3-5 返回餐具状态模块toolstatus(bool a)流程图
4. 源程序代码
//实验目的:通过实现哲学家进餐问题的同步深入了解和掌握进程同步和互斥的原理。
//设计要求:哲学家有N个,也定全体到达后开始讨论:在讨论的间隙哲学家进餐,
//每人进餐时都需使用刀、叉各一把,所有哲学家刀和叉都拿到后才能进餐。哲学家的人数、//餐桌上的布置自行设定,实现刀和叉的互斥使用算法的程序实现。
#include
#include
#include
#include
#include
using namespace std;
bool tools[6]; //全局变量,用餐工具
CRITICAL_SECTION cs; //信号量, 在线程中使用,临界区
class Philosopher
{
private:
int number;
int status; /*标记当前哲学家的状态,0表示正在等待(即处于饥饿状态),1表示得到两支筷子正在吃饭,2表示正在思考*/
public:
Philosopher(int num=0): status(2), number(num) { }