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

合集下载

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

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

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

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

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

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

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

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

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

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

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

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

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

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

操作系统哲学家进餐问题

操作系统哲学家进餐问题

操作系统实习报告一、设计目的:死锁是进程并发执行过程中可能出现的现象,所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局。

哲学家就餐问题是描述死锁的经典例子。

为了防止死锁,可以采用资源预分配法或者资源按序分配法。

资源预分配法是指进程在运行前一次性地向系统申请它所需要的全部资源,如果系统当前不能够满足进程的全部资源请求,则不分配资源, 此进程暂不投入运行,如果系统当前能够满足进程的全部资源请求, 则一次性地将所申请的资源全部分配给申请进程。

二、设计内容哲学家进餐问题的模拟。

三、开发环境windows环境,Myeclipse平台。

四、分析设计<一>实验原理哲学家进餐问题描述的是五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五只碗和五只筷子。

他们的生活方式是交替地进行思考和进餐。

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

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

由于:①只有拿到两只筷子时,哲学家才能吃饭;②如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;③任何一个哲学家在自己没有拿到两只筷子吃饭之前,决不放下自己手中的筷子。

则可能出现五个哲学家都饥饿时都拿着一直筷子。

这样就可能五个哲学家都用不上餐。

该问题可用记录型信号量解决,经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥使用,可以用一个信号量表示一只筷子,由这五个信号量组成信号量数组。

当哲学家饥饿时总是先拿其左边的筷子,成功后,再去拿右边的筷子,又成功后方可就餐。

进餐完,又先放下他左边的筷子,再放下右边筷子。

这个算法可以保证不会有两个相邻的哲学家同时就餐,但有可能引起死锁。

对于死锁问题可采取这样的几种解决方法:(1)至多只允许四个哲学家同时进餐,以保证至少有一个哲学家可以进餐,最终总会释放出他所用过的两只筷子,从而可使更多的哲学家进餐;(2)仅当左右两只筷子均可用时,才允许哲学家拿起筷子就餐(3)规定奇数号哲学家先拿起右边筷子,然后再去拿左边筷子,而偶数号哲学家则相反。

哲学家问题解决死锁的方法(一)

哲学家问题解决死锁的方法(一)

哲学家问题解决死锁的方法(一)哲学家问题解决死锁引言哲学家问题是一个典型的并发编程问题,它涉及到五位哲学家围坐在一张圆桌旁,每人面前有一盘饭和一只叉子。

哲学家的生活有两种状态:思考和进餐。

每个哲学家进餐时需要两只叉子,但是一次只能拿起一只,在他左右两边的哲学家也需要使用叉子。

这个问题的挑战在于如何避免死锁的发生。

方法一:使用死锁避免算法使用死锁避免算法是一种解决哲学家问题的常见方法。

该算法的基本思想是通过限制某些哲学家的进餐行为,以避免产生死锁。

1.限制偶数编号的哲学家先拿左手边的叉子,再拿右手边的叉子。

2.限制奇数编号的哲学家先拿右手边的叉子,再拿左手边的叉子。

3.对于哲学家的进餐过程,需要先检查叉子的可用性,如果叉子被其他哲学家使用,则等待。

方法二:使用资源分级策略资源分级策略是另一种解决哲学家问题的方法,它通过划分资源的优先级来避免死锁的发生。

1.将五只叉子按照优先级从高到低排序。

2.每个哲学家在进餐前需要先请求相应优先级的叉子。

3.偶数编号的哲学家优先请求左手边的叉子,再请求右手边的叉子。

4.奇数编号的哲学家优先请求右手边的叉子,再请求左手边的叉子。

方法三:使用资源分配策略资源分配策略是一种更加灵活的解决哲学家问题的方法,它通过动态分配资源来避免死锁。

1.创建一个共享的资源管理器,用于管理叉子的分配和释放。

2.每个哲学家在进餐前向资源管理器请求两只叉子。

3.资源管理器根据当前可用的叉子数量进行分配。

4.当一个哲学家进餐结束后,释放叉子,并通知资源管理器。

结论哲学家问题是一个复杂的并发编程问题,需要谨慎设计解决方案以避免死锁的发生。

通过使用死锁避免算法、资源分级策略和资源分配策略等方法,可以有效地解决哲学家问题,并保证系统的稳定性和高效性。

在实际应用中,可以根据具体需求选择适合的方法来解决死锁问题。

哲学家问题解决方法

哲学家问题解决方法

哲学家问题解决方法
哲学家问题是一个经典的并发编程问题,旨在解决多个哲学家共享有限资源
(如餐桌上的筷子)时可能发生的死锁情况。

在这个问题中,哲学家们围坐在一张圆桌旁,每个哲学家面前都有一只餐具桌子上有一定数量的筷子,而每个哲学家需要同时拿到两只筷子才能进食。

如果每个哲学家都试图先拿起同一边的筷子,那么就会造成死锁,导致每个哲学家都无法进食。

针对哲学家问题,有几种解决方法如下:
1.资源分级:通过给每个筷子分配唯一的编号,并规定哲学家只能按照编号递
增的顺序拿起筷子,可以有效避免死锁的出现。

在这种方法中,第一个哲学家先尝试拿起编号较小的筷子,如果成功则继续拿起编号较大的筷子,否则放下已拿起的筷子并等待。

其他哲学家按照相同顺序进行操作。

2.资源互斥:使用互斥锁(mutex)来确保同时只有一个哲学家能够拿起一对
筷子。

当一个哲学家准备进食时,他必须先尝试获得左边的筷子,如果成功则再尝试获得右边的筷子,反之则释放已拿起的筷子。

这种方法可以避免死锁情况的发生。

3.资源剥夺:在一段时间内限制某个哲学家可以进食的次数,使得其他哲学家
有机会获得筷子进食。

例如,当一个哲学家成功拿起筷子后,可以设置一个计时器,在超过一定时间未释放筷子时,系统强制将筷子夺取回来让其他哲学家使用。

这种方法可以避免某个哲学家长时间占用筷子,导致其他哲学家无法进食的情况。

总之,针对哲学家问题的解决方法主要包括资源分级、资源互斥和资源剥夺。

通过合理的设计和策略,我们可以解决哲学家问题,确保哲学家们能够公平地共享资源,避免死锁的发生。

实验一 哲学家就餐问题

实验一 哲学家就餐问题

实验一哲学家就餐问题一、实验目的1.熟练使用VC++6.0编译环境,调试并正确运行程序。

2.熟悉哲学家就餐问题流程。

3.理解哲学家就餐问题中出现的问题,进而掌握死锁的必要条件。

4.熟悉源程序中产生和防止死锁的算法,及其相关窗口操作。

二、实验原理1.问题描述:有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子,每个哲学家的行为时思考,饥饿,然后吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边取筷子。

2.防止死锁发生的分配方式:仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子。

这样要么一次占有两只筷子(所有线程需要的资源)进行下一步吃通心粉,然后释放所有的资源;要么不占用资源,这样就不可能产生死锁了。

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

4.程序运行说明:程序运行过程中会弹出一个MessageBox提示操作者操作:1)第一个对话框用于选择运行模式a.选择yes表示采用的是运行的防止死锁的方式,这样的话整个程序可以一直运行下去,不会产生死锁。

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

2)第二个对话框用于选择运行时,线程运行的时间a.选择yes线程时间比较短,很快就可以死锁。

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

三、实验过程及分析1.PhilosopherThread(LPVOID pVoid)函数伪代码1)不死锁方式Var mutexleftchopstick,mutexrightchopstick;Beging:Resting;Waiting;P{mutexleftchopstick};P{mutexrightchopstick};GetResource{leftchopstick,rightchopstick};Eating;V{mutexleftchopstick};V{mutexrightchopstick};End2)发生死锁方式Var mutexleftchopstick,mutexrightchopstick;Beging:Resting;Waiting;P{mutexleftchopstick};GetResource{leftchopstick};P{mutexrightchopstick};GetResource{rightchopstick};Eating;V{mutexleftchopstick};V{mutexrightchopstick};End2.代码分析1)不发生死锁时,哲学家迅速同时抢占两个筷子的资源,而若是不能同时抢占两只筷子则继续等待,知道有两只筷子空闲则抢占,这样就打破了死锁的必要条件。

计算机操作系统哲学家进餐问题的教学探讨

计算机操作系统哲学家进餐问题的教学探讨

计算机操作系统哲学家进餐问题的教学探讨
计算机操作系统哲学家进餐问题是一个经典的模拟问题,用于帮助学生理解线程同步、死锁和资源管理等操作系统的核心概念。

该问题描述了n个哲学家围坐在一张圆桌周围,每个哲学家面前有一盘食物,中间有n个筷子。

哲学家需要吃饭,但是每个哲学家只能使用自己左右两边的筷子来进餐。

如果哲学家发现左边或右边的筷子被占用,就会等待,直到筷子被释放。

这个问题中存在死锁的可能性。

在教学中,可以通过演示代码或编写代码来模拟这个问题的运行情况,帮助学生理解这些概念的实际应用。

例如,可以演示如何使用锁和条件变量来解决死锁问题,或者如何
使用信号量管理系统资源来避免死锁问题。

另外可以讨论不同的算法和策略,如顺序获取筷子,随机获取筷子等,来说明如何避免死锁的发生.
总之,通过这个问题的模拟,学生可以加深对操作系统的理解,并且对如何解决多线程并发问题有更深入的了解。

在教学探讨中,老师可以通过不同的模拟实验来说明线程同步和死锁的本质原理以及如何避免和解决这些问题。

鼓励学生进行自己的实验和探究,以加深对这些概念的理解。

关于哲学家就餐问题的分析代码.

关于哲学家就餐问题的分析代码.

关于哲学家就餐问题的分析代码.①总体思路: 都去拿左边的筷⼦,并且最后⼀个⼈不能去拿筷⼦(防⽌⼤家都拿了左边的筷⼦,没有右边的筷⼦,导致死锁了),解决死锁问题的办法就是同时只允许四位哲学家同时拿起同⼀边的筷⼦,这样就能保证⼀定会有⼀位哲学家能够拿起两根筷⼦完成进⾷并释放资源,供其他哲学家使⽤,从⽽实现永动,避免了死锁。

举个最简单的栗⼦,假定0~3号哲学家已经拿起了他左边的筷⼦,然后当4号哲学家企图去拿他左边的筷⼦的时候,将该哲学家的线程锁住,使其拿不到其左边的筷⼦,然后其左边的筷⼦就可以被3号哲学家拿到,然后3号哲学家进餐,释放筷⼦,然后更多的哲学家拿到筷⼦并进餐。

如何才能实现当4号哲学家企图拿起其左边的筷⼦的时候将该哲学家的线程阻塞?这个时候就要⽤到该问题的提出者迪杰斯特拉(这货还提出了迪杰斯特拉最短路径算法,著名的银⾏家算法也是他发明的)提出的信号量机制。

因为同时只允许有四位哲学家同时拿起左筷⼦,因此我们可以设置⼀个信号量r,使其初始值为4,然后每当⼀位哲学家企图去拿起他左边的筷⼦的时候,先对信号量做⼀次P操作,从⽽当第五位哲学家企图去拿做筷⼦的时候,对r做⼀次P操作,r = -1,由r < 0得第五位哲学家的线程被阻塞,从⽽不能拿起左筷⼦,因此也就避免了死锁问题。

然后当哲学家放下他左边的筷⼦的时候,就对r做⼀次V操作。

②在主线程和⼦线程中,避免了竞争关系.代码参考如下:/************************************ @file linux_zexuejia.c* @copyright ⽉光下的脚步 Co.,Ltd.ALL Right Reserved* @brief 使⽤信号量和互斥锁完成,哲学家就餐问题。

* @author 王有康* @data 2019、7、31* @version V1.1* @Last Modified 2018/10/25 wangyoukang* @note 当前版本是v1.1版本,以后需要修改,可以在上添加版本和修改⽇期* @note* @warning* @Function List :************************************/#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <time.h>#include <unistd.h>#include <pthread.h>#include <semaphore.h>#define N 5//互斥锁pthread_mutex_t chops[N];//信号量sem_t r;/*********************** @fn philosopher* @biref 每次只有4个⼈能够获得左⼿资源,这样不会死锁* @param philosopher number* @return* @other***********************/void philosopher(void *arg){int i = *(int *)arg;int left = i;int right = (i + 1)%N;while(1){printf("哲学家%d在思考问题\n",i);usleep(1000);printf("哲学家%d饿了\n",i);sem_wait(&r);pthread_mutex_lock(&chops[left]);printf("philosopher %d take left lock\n",i);pthread_mutex_lock(&chops[right]);printf("philosopher %d take right lock\n",i);printf("philosopher %d eat\n",i);usleep(1000);pthread_mutex_unlock(&chops[right]);printf("philosopher %d release right lock\n",i);pthread_mutex_unlock(&chops[left]);printf("philosopher %d realease left lock\n",i);sem_post(&r);}}/*********************** @fn philosopher* @biref 主函数* @param* @return* @other***********************/int main(int argc,char **argv){int i = 0,*ptr;pthread_t tid[N];for(i = 0;i < N;i++){pthread_mutex_init(&chops[i],NULL);}sem_init(&r,0,4);for(i = 0;i < N;i++){//防⽌主线程和对等线程竞争,给线程和主线程分配不同的内存区域。

死锁—哲学家吃饭问题

死锁—哲学家吃饭问题

死锁—哲学家吃饭问题由于线程能被阻塞,更由于synchronized方法能阻止其它线程访问本对象,因此有可能会出现如下这种情况:线程一在等线程二(释放某个对象),线程二又在等线程三,这样依次排下去直到有个线程在等线程一。

这样就形成了一个环,每个线程都在等对方释放资源,而它们谁都不能运行。

这就是所谓的死锁(deadlock)。

如果程序一运行就死锁,那倒也简单了。

你可以马上着手解决这个问题。

但真正的麻烦在于,程序看上去能正常运行,但是却潜伏着会引起死锁的隐患。

或许你认为这里根本就不可能会有死锁,而bug 也就这样潜伏下来了。

直到有一天,让某个用户给撞上了(而且这种bug还很可能是不可重复的)。

所以对并发编程来说,防止死锁是设计阶段的一个重要任务。

下面我们来看看由Dijkstra发现的经典的死锁场景:哲学家吃饭问题。

原版的故事里有五个哲学家(不过我们的例程里允许有任意数量)。

这些哲学家们只做两件事,思考和吃饭。

他们思考的时候,不需要任何共享资源,但是吃饭的时候,就必须坐到餐桌旁。

餐桌上的餐具是有限的。

原版的故事里,餐具是叉子,吃饭的时候要用两把叉子把面条从碗里捞出来。

但是很明显,把叉子换成筷子会更合理,所以:一个哲学家需要两根筷子才能吃饭。

现在引入问题的关键:这些哲学家很穷,只买得起五根筷子。

他们坐成一圈,两个人的中间放一根筷子。

哲学家吃饭的时候必须同时得到左手边和右手边的筷子。

如果他身边的任何一位正在使用筷子,那他只有等着。

这个问题之所以有趣就在于,它演示了这么一个程序,它看上去似乎能正常运行,但是却容易引起死锁。

你可以自己试试,用命令行参数调节哲学家的数量和思考的时间。

如果有很多哲学家,而且/或者他们思考的时间很长,或许你永远也碰不到死锁,但是死锁的可能性总还是在的。

默认的命令行参数会让它很快地死锁://: c13:DiningPhilosophers.java// Demonstrates how deadlock can be hidden in a program.// {Args: 5 0 deadlock 4}import java.util.*;class Chopstick {private static int counter = 0;private int number = counter++;public String toString() {return"Chopstick " + number;}}class Philosopher extends Thread {private static Random rand = new Random();private static int counter = 0;private int number = counter++;private Chopstick leftChopstick;private Chopstick rightChopstick;static int ponder = 0; // Package accesspublic Philosopher(Chopstick left, Chopstick right) {leftChopstick = left;rightChopstick = right;start();}public void think() {System.out.println(this + " thinking");if(ponder > 0)try {sleep(rand.nextInt(ponder));} catch(InterruptedException e) {throw new RuntimeException(e);}}public void eat() {synchronized(leftChopstick) {System.out.println(this + " has "+ this.leftChopstick + " Waiting for "+ this.rightChopstick);synchronized(rightChopstick) {System.out.println(this + " eating");}}}public String toString() {return"Philosopher " + number;}public void run() {while(true) {think();eat();}}}public class DiningPhilosophers {public static void main(String[] args) {if(args.length < 3) {System.err.println("usage:\n" +"java DiningPhilosophers numberOfPhilosophers " +"ponderFactor deadlock timeout\n" +"A nonzero ponderFactor will generate a random " +"sleep time during think().\n" +"If deadlock is not the string " +"'deadlock', the program will not deadlock.\n" +"A nonzero timeout will stop the program after " +"that number of seconds.");System.exit(1);}Philosopher[] philosopher =new Philosopher[Integer.parseInt(args[0])];Philosopher.ponder = Integer.parseInt(args[1]);Chopstickleft = new Chopstick(),right = new Chopstick(),first = left;int i = 0;while(i < philosopher.length - 1) {philosopher[i++] =new Philosopher(left, right);left = right;right = new Chopstick();}if(args[2].equals("deadlock"))philosopher[i] = new Philosopher(left, first);else// Swapping values prevents deadlock:philosopher[i] = new Philosopher(first, left);// Optionally break out of program:if(args.length >= 4) {int delay = Integer.parseInt(args[3]);if(delay != 0)new Timeout(delay * 1000, "Timed out");}}} ///:~Chopstick和Philosopher都包含一个能自动递增的static counter。

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

红河学院课程设计报告操作系统课程名称:6个哲学家进餐设计题目:院系:工学院专业:计算机科学与技术班级:11计科班曹永前设计者:学号:201101030466指导教师:韦相2013 年 5 月26 日1. 问题描述:一个房间内有6个哲学家,他们的生活就是思考和进食。

哲学家思考后,过一定的时间就会饥饿,饥饿之后就想吃饭,吃饭后再思考。

房间里有一张圆桌,桌子周围放有五把椅子,分别属于五位哲学家每两位哲学家之间有一把叉子,哲学家进食时必须同时使用左右两把叉子。

2. 问题分析1、写出哲学家进餐的算法描述。

用六只筷子解决需要用两双筷子来进餐的六个哲学家,由于每个哲学家都需要其周围的两只筷子,所以筷子是公用信号量,这久需要设置一个互斥信号量,来使六个哲学家互斥的进餐.具体做法将六个信号量设置为0-5,用pv 源于来控制信号量,并将六个哲学家分别编号为0-5.经过仔细分析我们会发现,有这样一个问题存在,就是当每个哲学家都申请到他周围的一只筷子时,由于他们每人都只有一只筷子无法进餐,没有进餐他们就无法释放他们已经得得到的筷子,这样是进餐出于一种僵局,无法继续下去,这就是死锁问题.2、死锁问题的分析与具体的解决方法。

死锁问题就是当每个哲学家都拿到且只拿到一只筷子,这样每个哲学家都无法进餐,也无法释放所得到的筷子,所以解决死锁我们就要从这入手,就是怎样去预防使所有哲学家不要同时去申请他们同一方向的筷子.根据这解决死锁的方法有以下几种:a.每一次最多只能有五个哲学家申请进餐.这样其中的一个哲学家就能申请到两只筷子,就能够进餐,再将筷子释放给其他哲学家进餐.b.用AND信号量,就是哲学家需同时申请其左右两边的筷子,两边都有资源的时候,才能让这个哲学家得到资源,这样哲学家只要申请到筷子就能进餐, 再将筷子释放给其他哲学家进餐.c.用管程机制来实现。

d.我们前面已经将每个哲学家都分配了一个编号,我们可以编号为奇数的哲学家首先去申请其左边的筷子,再去申请其右手边的筷子;让编号为偶数的哲学家,先去申请其右边的筷子,再去申请其左边的筷子.我们可以看出编号为奇数的哲学家左边,与编号为偶数的哲学家的右边为同一只筷子,当其中一个哲学家拿到此筷子后,他另一边的筷子也是空闲的,这样就能避免死锁.主程序中我使用的是最后一种避免死锁的方法.3、用C程序实现哲学家进餐。

(注:可以使用共享变量的方式,也可以使用信号量的方式或其他方法来实现)3.程序清单#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <signal.h>#include <stdio.h>#include <sys/wait.h>#include <stdlib.h>#define N 6 //人数#define THINKTIME 3 // 思考时间#define EATTIME 2 //进餐时间void pop(),vop(),zxj(),think(),eat(); // 初始化main(){int i,semid,pid; //定义变量i为哲学家的编号,semid 信号量semid = semget(0x1234,6,0666|IPC_CREAT);for (i=0;i<N;i++){if (semctl(semid,i,SETV AL,1)==-1)perror("sem set value error");}int pid1,pid2,pid3,pid4,pid5,pid6;while ((pid1=fork())==-1);if (pid1==0){int num=1;zxj(0,semid,num);}while((pid2=fork())==-1);if (pid2==0){int num=1;zxj(1,semid,num);}while ((pid3=fork())==-1);if (pid3==0){int num=1;zxj(2,semid,num);}while ((pid4=fork())==-1);if (pid4==0){int num=1;zxj(3,semid,num);}while ((pid5=fork())==-1);if (pid5==0){int num=1;zxj(4,semid,num);}while ((pid6=fork())==-1);if (pid6==0){int num=1;zxj(5,semid,num);}else{sleep(30);kill(0,15);exit(0);}}void zxj(int i, int semid, int num){while (1)if(i%2==0){think(i);pop(semid ,(i+1)%6);pop(semid,i);eat(i,num);num++;vop(semid,(i+1)%6);vop(semid,i);}else{think(i);pop(semid,i);pop(semid ,(i+1)%6);eat(i,num);num++;vop(semid,i);vop(semid,(i+1)%6);}}void think(int i){printf("我是第%d个哲学家,正在思考,思考时间是%d秒.\n",i,i+THINKTIME);sleep(i+THINKTIME);}void eat(int i,int num){printf("我是第%d个哲学家,正在吃第%d次饭,吃饭时间是%d 秒.\n",i,num,i+EATTIME);sleep(i+EATTIME);}void pop (int semid,int semnum){struct sembuf thesops;thesops.sem_num= semnum;thesops.sem_op = -1;thesops.sem_flg = SEM_UNDO;semop(semid,&thesops,1);}void vop (int semid,int semnum){struct sembuf thesops;thesops.sem_num= semnum;thesops.sem_op = 1;thesops.sem_flg = SEM_UNDO;semop(semid,&thesops,1);}4.运行结果[root@localhost ~]# cc -o qz qz.c[root@localhost ~]# ./qz我是第0个哲学家,正在思考,思考时间是3秒.我是第1个哲学家,正在思考,思考时间是4秒.我是第2个哲学家,正在思考,思考时间是5秒.我是第3个哲学家,正在思考,思考时间是6秒.我是第4个哲学家,正在思考,思考时间是7秒.我是第5个哲学家,正在思考,思考时间是8秒.我是第0个哲学家,正在吃第1次饭,吃饭时间是2秒. 我是第2个哲学家,正在吃第1次饭,吃饭时间是4秒. 我是第0个哲学家,正在思考,思考时间是3秒.我是第4个哲学家,正在吃第1次饭,吃饭时间是6秒. 我是第2个哲学家,正在思考,思考时间是5秒.我是第1个哲学家,正在吃第1次饭,吃饭时间是3秒. 我是第1个哲学家,正在思考,思考时间是4秒.我是第0个哲学家,正在吃第2次饭,吃饭时间是2秒. 我是第4个哲学家,正在思考,思考时间是7秒.我是第3个哲学家,正在吃第1次饭,吃饭时间是5秒. 我是第5个哲学家,正在吃第1次饭,吃饭时间是7秒. 我是第0个哲学家,正在思考,思考时间是3秒.我是第1个哲学家,正在吃第2次饭,吃饭时间是3秒. 我是第3个哲学家,正在思考,思考时间是6秒.我是第1个哲学家,正在思考,思考时间是4秒.我是第2个哲学家,正在吃第2次饭,吃饭时间是4秒. 我是第5个哲学家,正在思考,思考时间是8秒.我是第4个哲学家,正在吃第2次饭,吃饭时间是6秒. 我是第0个哲学家,正在吃第3次饭,吃饭时间是2秒. 我是第2个哲学家,正在思考,思考时间是5秒.我是第0个哲学家,正在思考,思考时间是3秒.我是第1个哲学家,正在吃第3次饭,吃饭时间是3秒. 我是第1个哲学家,正在思考,思考时间是4秒.我是第0个哲学家,正在吃第4次饭,吃饭时间是2秒.我是第3个哲学家,正在吃第2次饭,吃饭时间是5秒.我是第4个哲学家,正在思考,思考时间是7秒.我是第0个哲学家,正在思考,思考时间是3秒.我是第5个哲学家,正在吃第2次饭,吃饭时间是7秒.已终止[root@localhost ~]#5.讨论上述代码中我只是用了改变申请资源次序的方法来预防死锁,在前面的问题分析是我也提到了,其预防死锁的方法并不唯一,下面讲讨论是用其他方法预防死锁问题。

1.是用互斥申请资源就是在同一时刻最多只可以有五位哲学家申请进餐,设置信号量mutex 初始值为5,这样就保证了5个哲学家中至少有1人可以拿到两只筷子,从而避免死锁。

伪码:Mutex=5;Pidi(i=0,1,2,3,4,5)Think();wait(mutex);wait(chopstick[i]);wait(chopstick[i+1] mod 6);signal(mutex);eat();signal(chopstick[i]);signal(chopstick[i+1] mod 6);think();2.采用AND信号量机制AND的基本思想是,将进程所需要的所有资源一次性全部分配给它,但是要有一个资源不能分配给进程,则其他资源也不能分配给该进程(要么所需资源全分配,要么就直接不分配)。

伪码:Pid i(i=0,1,2,3,4,5)Think();swait(chopstick[i],chopstick(i+1) mod 6);eat();signal(chopstick[i],chopstick(i+1) mod 6);think();6.小结1.哲学家问题是进程管理中一个非常经典的例题,是实现多线程同步的问题,这个问题的实现对于我们对进程同步的问题的理解有促进作用。

2.通过设计是我能够熟练的掌握wait 和signal原语;通过对信号量的控制实现进程的互斥与等待;模拟多个进程之间的并发执行。

3.在做的过程当中要不断的上网查阅资料来实现程序功能,课程设计多于的解决问题的能力,以及独立思考的能力都有所锻炼。

4.实践是对理论学习的一个巩固,加深了对理论知识的理解,在设计的过程当中积累经验,并促进理论知识的学习。

相关文档
最新文档