哲学家就餐问题实验报告
6个哲学家进餐问题预防死锁
红河学院课程设计报告操作系统课程名称:6个哲学家进餐设计题目:院系:工学院专业:计算机科学与技术班级:11计科班曹永前设计者:学号:201101030466指导教师:韦相2013 年 5 月26 日1. 问题描述:一个房间内有6个哲学家,他们的生活就是思考和进食。
哲学家思考后,过一定的时间就会饥饿,饥饿之后就想吃饭,吃饭后再思考。
房间里有一张圆桌,桌子周围放有五把椅子,分别属于五位哲学家每两位哲学家之间有一把叉子,哲学家进食时必须同时使用左右两把叉子。
2. 问题分析1、写出哲学家进餐的算法描述。
用六只筷子解决需要用两双筷子来进餐的六个哲学家,由于每个哲学家都需要其周围的两只筷子,所以筷子是公用信号量,这久需要设置一个互斥信号量,来使六个哲学家互斥的进餐.具体做法将六个信号量设置为0-5,用pv 源于来控制信号量,并将六个哲学家分别编号为0-5.经过仔细分析我们会发现,有这样一个问题存在,就是当每个哲学家都申请到他周围的一只筷子时,由于他们每人都只有一只筷子无法进餐,没有进餐他们就无法释放他们已经得得到的筷子,这样是进餐出于一种僵局,无法继续下去,这就是死锁问题.2、死锁问题的分析与具体的解决方法。
死锁问题就是当每个哲学家都拿到且只拿到一只筷子,这样每个哲学家都无法进餐,也无法释放所得到的筷子,所以解决死锁我们就要从这入手,就是怎样去预防使所有哲学家不要同时去申请他们同一方向的筷子.根据这解决死锁的方法有以下几种:a.每一次最多只能有五个哲学家申请进餐.这样其中的一个哲学家就能申请到两只筷子,就能够进餐,再将筷子释放给其他哲学家进餐.b.用AND信号量,就是哲学家需同时申请其左右两边的筷子,两边都有资源的时候,才能让这个哲学家得到资源,这样哲学家只要申请到筷子就能进餐, 再将筷子释放给其他哲学家进餐.c.用管程机制来实现。
d.我们前面已经将每个哲学家都分配了一个编号,我们可以编号为奇数的哲学家首先去申请其左边的筷子,再去申请其右手边的筷子;让编号为偶数的哲学家,先去申请其右边的筷子,再去申请其左边的筷子.我们可以看出编号为奇数的哲学家左边,与编号为偶数的哲学家的右边为同一只筷子,当其中一个哲学家拿到此筷子后,他另一边的筷子也是空闲的,这样就能避免死锁.主程序中我使用的是最后一种避免死锁的方法.3、用C程序实现哲学家进餐。
广东海洋大学 哲学家就餐问题
GDOU-B-11-112广东海洋大学学生实验报告书(学生用表)实验名称哲学家就餐问题课程名称计算机操作系统学院(系) 数学与计算机学院专业班级学生姓名学号实验地点实验日期实验哲学家就餐问题1.1.1服务生解法一个简单的解法是引入一个餐厅服务生,哲学家必须经过他的允许才能拿起餐叉。
因为服务生知道哪只餐叉正在使用,所以他能够作出判断避免死锁。
为了演示这种解法,假设哲学家依次标号为A至E。
如果A和C在吃东西,则有四只餐叉在使用中。
B坐在A和C之间,所以两只餐叉都无法使用,而D和E之间有一只空余的餐叉。
假设这时D想要吃东西。
如果他拿起了第五只餐叉,就有可能发生死锁。
相反,如果他征求服务生同意,服务生会让他等待。
这样,我们就能保证下次当两把餐叉空余出来时,一定有一位哲学家可以成功的得到一对餐叉,从而避免了死锁。
1.1.2资源分级解法另一个简单的解法是为资源(这里是餐叉)分配一个偏序或者分级的关系,并约定所有资源都按照这种顺序获取,按相反顺序释放,而且保证不会有两个无关资源同时被同一项工作所需要。
在哲学家就餐问题中,资源(餐叉)按照某种规则编号为1至5,每一个工作单元(哲学家)总是先拿起左右两边编号较低的餐叉,再拿编号较高的。
用完餐叉后,他总是先放下编号较高的餐叉,再放下编号较低的。
在这种情况下,当四位哲学家同时拿起他们手边编号较低的餐叉时,只有编号最高的餐叉留在桌上,从而第五位哲学家就不能使用任何一只餐叉了。
而且,只有一位哲学家能使用最高编号的餐叉,所以他能使用两只餐叉用餐。
当他吃完后,他会先放下编号最高的餐叉,再放下编号较低的餐叉,从而让另一位哲学家拿起后边的这只开始吃东西。
尽管资源分级能避免死锁,但这种策略并不总是实用的,特别是当所需资源的列表并不是事先知道的时候。
例如,假设一个工作单元拿着资源3和5,并决定需要资源2,则必须先要释放5,之后释放3,才能得到2,之后必须重新按顺序获取3和5。
对需要访问大量数据库记录的计算机程序来说,如果需要先释放高编号的记录才能访问新的记录,那么运行效率就不会高,因此这种方法在这里并不实用。
操作系统哲学家问题实验报告
实验报告三实验名称:一、调试验证“有限缓冲”经典同步问题二、利用Java同步解决“哲学家进餐”问题日期:2015-11-5 班级:13级计科学号:姓名:一、实验目的1.了解信号量的使用2.掌握正确使用同步机制的方法3.实现生产者消费者进程的互斥与同步4.实现java同步解决“哲学家进餐”问题二、实验内容1.调试验证“有限缓冲”经典同步问题2.利用Java同步解决“哲学家进餐”问题三、项目要求与分析1.“有限缓冲”经典同步问题(1)问题描述有一群生产者进程在生产产品,此产品提供给消费者去消费。
为使生产者和消费者进程能并发执行,在它们之间设置一个具有n个缓冲池,生产者进程可将它所生产的产品放入一个缓冲池中,消费者进程可从一个缓冲区取得一个产品消费。
(2)问题分析设两个同步信号量:一个说明空缓冲区的数目,用empty表示,初值为有界缓冲区的大小N,另一个说明已用缓冲区的数目,用full表示,初值为0。
由于在执行生产活动和消费活动中要对有界缓冲区进行操作。
有界缓冲区是一个临界资源,必须互斥使用,所以另外还需要设置一个互斥信号量mutex,其初值为1。
2.“哲学家进餐”问题(1)问题描述假如所有的哲学家都同时拿起左侧筷子,看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子,如此这般,永远重复。
对于这种情况,即所有的程序都在无限制地运行,但是都无法得到任何进展,即出现饿死,所有的哲学家都吃不上饭。
规定在拿起左侧的筷子后,先检查右面的筷子是否可用。
如果不可用,则放下左侧的筷子,等一段时间后再重复整个过程。
(2)问题分析当出现以下情形,在某一瞬间,所有的哲学家都同时启用这个算法,拿起左侧的筷子,而看到右侧筷子都不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此永远重复下去。
对于这种情况,所有的程序都在运行,但却都无法取得进展,即出现饿死,所有的哲学家都吃不上饭。
解决死锁问题:为了避免死锁,把哲学家分为三种状态:思考,饥饿(等待),进食,并且一次拿起两只筷子,否则不拿。
哲学家就餐问题实验报告
南昌大学实验报告学生姓名:倪焕学号:8000114018 专业班级:软件工程141班实验类型:■验证□综合□设计□创新实验日期:2016.5.24 实验成绩:一、实验项目名称哲学家就餐问题二、实验目的利用PV操作解决哲学家就餐问题三、软硬件环境软件:Visual Studio2010硬件:PC机一台四、实验内容结果//哲学家就餐问题的解法#include <windows.h>#include <process.h>#include <stdlib.h>#include <stdio.h>#include <iostream>using namespace std; //命名空间std内定义的所有标识符都有效const unsigned int PHILOSOPHER_NUM=5; //哲学家数目const char THINKING=1; /*标记当前哲学家的状态,1表示等待,2表示得到饥饿,3表示正在吃饭*/const char HUNGRY=2;const char DINING=3;HANDLE hPhilosopher[5]; //定义数组存放哲学家/*HANDLE(句柄)是windows操作系统中的一个概念。
指的是一个核心对象在某一个进程中的唯一索引*/HANDLE semaphore[PHILOSOPHER_NUM]; // semaphore 用来表示筷子是否可用HANDLE mutex; // Mutex用来控制安全输出DWORD WINAPI philosopherProc( LPVOID lpParameter) //返回DWORD(32位数据)的API 函数philosopherProc{int myid; //哲学家idchar idStr[128];char stateStr[128];char mystate;int ret;unsigned int leftFork; //左筷子unsigned int rightFork; //右筷子myid = int(lpParameter);itoa(myid, idStr, 10);WaitForSingleObject(mutex, INFINITE);cerr << "philosopher " << myid << " begin......" << endl;ReleaseMutex(mutex);mystate = THINKING; //初始状态为THINKING leftFork = (myid) % PHILOSOPHER_NUM;rightFork = (myid + 1) % PHILOSOPHER_NUM;while (true){switch(mystate){case THINKING:mystate = HUNGRY; // 改变状态strcpy(stateStr, "HUNGRY");break;case HUNGRY:strcpy(stateStr, "HUNGRY");ret = WaitForSingleObject(semaphore[leftFork], 0); // 先检查左筷子是否可用if (ret == W AIT_OBJECT_0){ret = WaitForSingleObject(semaphore[rightFork], 0); //左筷子可用就拿起,再检查右筷子是否可用if (ret == WAIT_OBJECT_0){mystate = DINING; // 右筷子可用,就改变自己的状态strcpy(stateStr, "DINING");}else{ReleaseSemaphore(semaphore[leftFork], 1, NULL); // 如果右筷子不可用,就把左筷子放下}}break;case DINING:// 吃完后把两支筷子都放下ReleaseSemaphore(semaphore[leftFork], 1, NULL);ReleaseSemaphore(semaphore[rightFork], 1, NULL);mystate = THINKING; // 改变自己的状态strcpy(stateStr, "THINKING");break;}// 输出状态WaitForSingleObject(mutex, INFINITE);cerr << "philosopher " << myid << " is : " << stateStr << endl;ReleaseMutex(mutex);Sleep(5000);}}int main(){int i,run;run = 1;mutex = CreateMutex(NULL, false, NULL);for (i=0; i<PHILOSOPHER_NUM; i++){semaphore[i] = CreateSemaphore(NULL, 1, 1, NULL); //创建一个新的信号量hPhilosopher[i]=CreateThread(NULL,0,philosopherProc,LPVOID(i),CREATE_SUSPENDED,0); //创建一个新线程ResumeThread(hPhilosopher[i]); //线程恢复函数Sleep(15);}while(run){Sleep(5000);cerr<<"**************************************"<<endl;}return 0; }五、实验体会通过本次实验,首先是对哲学家就餐问题有了更深的了解,而通过PV操作,很好的解决了哲学家就餐问题,这使得我对PV操作更加熟悉,同时帮助我理解了原先不太懂的地方,希望强加练习。
实验一 哲学家就餐问题
实验一哲学家就餐问题一、实验目的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)不发生死锁时,哲学家迅速同时抢占两个筷子的资源,而若是不能同时抢占两只筷子则继续等待,知道有两只筷子空闲则抢占,这样就打破了死锁的必要条件。
五个哲学家吃饭问题详细解答
五个哲学家吃饭问题详细解答在一个阳光明媚的下午,五个哲学家聚在一起,准备享用一顿丰盛的午餐。
听起来很简单吧?但实际上,这顿饭可没那么容易!让我们来看看这群头脑发达的哲学家是如何在吃饭问题上纠结的。
1. 场景设定1.1 哲学家的基本设定这五位哲学家,一个比一个聪明。
他们分别是苏格拉底、柏拉图、康德、尼采和海德格尔。
你可以想象,他们脑袋里装的全是复杂的哲学思想,而不是食物的搭配。
所以,当这五位坐下来,面对一桌子美味的食物时,事情就开始变得有趣了。
1.2 吃饭的挑战问题来了:他们每个人都必须遵守一个规则——不可以同时吃饭,得轮流。
你想想,五个哲学家加上一个轮流吃饭的规则,这可真是“见鬼了”的挑战!想要吃上一口美味的菜,简直比推理一个哲学命题还难。
他们轮流吃饭的原则,真是把这顿饭变成了一场智力的较量。
2. 各自的哲学观2.1 苏格拉底的理性苏格拉底首先站出来,他一边抚摸着自己的胡须,一边说:“吃饭嘛,首先得用理性来解决问题。
”他鼓励大家先讨论,谁应该先吃,谁应该后吃。
他认为,只有通过理性对话,才能达到最佳的吃饭方案。
可是,你能想象吗?这一讨论持续了整整一个小时,食物都快冷掉了!2.2 柏拉图的理想接着柏拉图出场,他满脸严肃地说:“我们要追求理想的吃饭方式。
”他想出了一个绝妙的主意:每个人都应该依照自己的德性来决定吃的顺序。
结果,大家一顿争论,谁的德性更高?苏格拉底说他是智者,康德坚持说自己是道德之父,而尼采则跳出来,吼着“超人才能吃超好的饭!”搞得大家乱成一团,吃的机会又飞了。
3. 饥饿的对抗3.1 食物的诱惑这时,桌子上的食物开始散发出诱人的香气,真是令人垂涎欲滴。
五位哲学家每个人的肚子都开始抗议,仿佛在唱着“我们要吃饭”的歌。
吃饭这件事,从理性讨论变成了一场生存竞争。
每个人都在默默地想着:“快点!要是再不吃,我的哲学思想就要被饿死了!”3.2 轮流的尴尬最终,他们决定采取轮流吃饭的方式。
可当轮到康德的时候,他又开始喋喋不休,讲起了“绝对命令”的哲学,让其他人都想打瞌睡。
试验1-哲学家就餐问题
实验2. 类、对象、继承及多态实验目的:理解Java对象的面向对象的特征以及在编程中的应用。
实验内容:1、验证对象作为参数传递是引用传递,而普通数据类型为值传递。
2、验证构造方法和静态属性与方法专属于类,而其他属性和方法虽然在类中定义,但是为对象而定义。
3、验证子类对象实例化时,通过继承,不仅将public、protected、缺省的属性和方法拷贝到对象当中,也将父类的私有属性拷贝到对象当中。
4、编写程序,体会类在重载情况下的相互调用,体会构造方法重载的调用方式。
5、编程体现this的三种用法,super的两种用法,指出this.属性在什么情况下不可以省略,指出super.成员方法在什么情况下不能省略,指出this指代对象的作用。
6、设计Src和Dis两个类, Src中有一个被封装的属性,类型为int(要求为非负值),每当我们通过特定方法更改Src对象中的这个属性后,Dis对象都能得到通知,并向Src发消息获得此属性值实验要求:1、程序以能证明和说明实验内容当中提出的问题为实现标准。
2、程序应有良好的书写规范,在类名定义、包名定义、变量定义、常量定义上遵从规范,同时程序在书写上应有良好的缩进层次。
3、实验报告中应有实验体会和收获等方面。
准备工具:1、JDK1.3以上版本,设置环境变量,搭建编译和运行环境。
1、搭建环境。
2、选用Application进行验证。
实验3. 多线程综合设计实验目的:理解Java语言中的多线程和异常处理,并将二者结合起来设计一个综合程序,实现特定的应用功能。
实验内容:1、7名哲学家同桌就餐,演示哲学家就餐问题中死锁现象的出现,并说明原因2、给出一种解决方案,保证多线程下不出现死锁,并说明这样实现的理由实验要求:1、必须有多线程和异常的内容,其中多线程需要处理多线程同步,如还有同步通信则更好;异常需要有异常抛出、异常捕获、异常嵌套捕获等内容,如有自定义异常类则更好。
2、程序当中产生异常的点很多,在一个大的应用程序当中(有众多的类),无论哪种异常发生后,如何集中在一处统一给出中文提示。
哲学家就餐问题实验报告
哲学家就餐问题实验报告姓名:何绍金班级:自动化1202学号:201203870408指导教师:张健2014年11月22日一.实验题目经典的同步问题——哲学家就餐问题设计。
二.实验内容1.实验要求有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃通心粉.为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。
2.程序流程图图1.主程序模块流程图开始定义信号量tools[5] 定义哲学家类对象P1-P5哲学家的状态发生改变;P1.change();P2.change();P3.change();P4.change();P5.change()输出当前状态停止程序结束否图2.状态改变模块流程图哲学家处于的状态否 哲学家处于思考状态是状态改为等待否 哲学家处于等待是 左右手筷子均空闲是 拿起左右手筷子状态改为就餐结束开始是 放下左右手工具 状态为思考 Status==2图3.返回哲学家状态流程图图4返回餐具状态模块流程图3.测试结果图5 测试结果1图6 测试结果2图7 测试结果34.结果分析和小结(1)程序分为四大模块,一步步解决了哲学家状态及状态改变的问题,筷子的“闲”、“用”问题;实现了哲学家等待、吃饭、思考三个过程的转换循环,并且避免了死锁问题;让临界资源得到了充分的利用。
(2)这次实验让我学会分模块解决问题,怎样运用互斥锁对临界资源进行管理;此外自己在编程上及一些函数的认识仍存在较大的问题,以后应该多多实践,提高自己的反应速度,加强逻辑思维能力。
三.程序源代码#include <windows.h>#include <time.h>#include <string>#include <iostream>#include <assert.h>using namespace std;bool tools[5]; //全局变量,用餐工具CRITICAL_SECTION cs; //信号量, 在线程中使用,临界区class Philosopher{private:int number;int status; /*标记当前哲学家的状态,0表示正在等待(即处于饥饿状态),1表示得到两支筷子正在吃饭,2表示正在思考*/public:Philosopher(int num=0): status(2), number(num) { }const int find(){return number;}const int getinfo(){ return status; }void Change() ; //状态改变函数void dead_lock();};/////////void Philosopher::dead_lock(){EnterCriticalSection (&cs) ; //进入临界区string s;if(status==1){tools[number%5]=true;// tools[(number-1)%5]=true;status=2;}else if(status==2){status=0;//tools[(number-1)%5]=false;//tools[(number-1)%5]=true;}else if(status==0){tools[number%5]=false;tools[(number-1)%5]=false;status=1;}LeaveCriticalSection (&cs) ;// cout<<"*********";}/////////void Philosopher::Change(){EnterCriticalSection (&cs) ; //进入临界区if(status==1) //正在进餐{tools[number%5]=true; //放下左手工具tools[(number-1)%5]=true; //放下右手工具status=2; //改变状态为思考}else if(status==2) //思考中{status=0; //改变状态为等待}else if(status==0) //等待中{if(tools[number%5]&&tools[(number-1)%5]) //左右手两边工具均为空闲状态{tools[number%5]=false; //拿起左手工具tools[(number-1)%5]=false; //拿起右手工具status=1;}}LeaveCriticalSection (&cs) ;}string print(Philosopher *pA){//pA->Change();int i=pA->getinfo();string str;if(i==0)str="等待";else if(i==1)str="就餐";else str="思考";return str;}string toolstatus(bool a){string state;if(a==true)state="闲";if(a==false)state="用";return state;}int main(){char con='y'; //判断是否继续// con = 'n';for(int i=0;i<5;i++)tools[i]=true; //筷子都未使用,初始化Philosopher P1(1),P2(2),P3(3),P4(4),P5(5);InitializeCriticalSection (&cs) ; //初始化初始化临界区cout<<"-----------------------状态说明示意图:-----------------------"<<endl; cout<<" "<<"哲学家1号的状态"<<" "<<endl;cout<<" 筷子0的状态"<<" "<<"筷子1的状态"<<endl;cout<<"哲学家5号的状态"<<" "<<"哲学家2号的状态"<<endl; cout<<" 筷子4的状态"<<" "<<"筷子2的状态"<<endl;cout<<" 哲学家4号的状态"<<" "<<"哲学家3号的状态"<<endl; cout<<" "<<"筷子3的状态"<<endl;//cout<<" "<<"哲学家3号的状态"<<" "<<endl;cout<<"筷子的状态,用表示使用中,闲表示空闲中。
哲学家实验报告
哲学家实验报告1. 引言本报告旨在介绍和讨论著名的哲学家就餐问题,该问题描述了一组哲学家在共享一张圆桌时遇到的资源竞争和死锁问题。
在实验中,我们将探讨不同的解决方案以及它们的有效性和局限性。
2. 实验背景在哲学家就餐问题中,有五个哲学家坐在一张圆桌周围,并且每个哲学家面前都有一盘面条和一只叉子。
这些哲学家在思考时会感到饥饿,因此需要进食。
然而,该圆桌上只有五只叉子供他们共享使用。
每个哲学家必须同时持有左右两只叉子才能进食。
由于叉子限制,哲学家们可能会遇到资源竞争导致饥饿和死锁的问题。
我们将利用计算机模拟该问题,并通过编写程序来探索不同的解决方案。
3. 实验步骤3.1 单纯实现在一开始的实验中,我们将使用简单的算法来模拟哲学家就餐问题。
我们假设哲学家们按照顺序获取叉子,并按照相同的顺序放下叉子。
然而,这种实现方式容易导致死锁情况的发生。
3.2 解决死锁问题为了解决死锁问题,我们可以引入等级制度来确保哲学家们按照一定的顺序获取叉子。
例如,我们可以规定每个哲学家只有在左右两边的叉子都可用时才可以进食。
这样,哲学家们将会按照固定的顺序获取叉子,从而避免死锁的发生。
3.3 引入资源管理者为了更好地管理叉子的使用,我们可以引入一个资源管理者来控制叉子的获取和释放。
资源管理者可以通过为每个叉子分配一个状态(被使用或空闲)来跟踪叉子的情况。
哲学家将需要向资源管理者请求获取叉子,如果叉子不可用,则将会阻塞直到叉子可用。
3.4 优化方案除了上述解决方案,还有其他一些优化方案可以被采用。
例如,可以引入超时机制,以防止某个哲学家无限等待叉子。
还可以引入更复杂的调度算法来控制叉子的分配。
4. 结果和讨论通过实验,我们发现在一些简单的情况下,单纯实现的算法可能会导致死锁的发生。
然而,通过引入等级制度和资源管理者,我们可以成功地避免死锁,并使得哲学家们能够正常地就餐。
此外,我们还发现不同的解决方案在效率和公平性方面存在差异。
操作系统实验报告哲学家就餐
操作系统实验报告哲学家就餐一、实验目的:通过模拟哲学家就餐问题,了解并掌握操作系统中的进程同步机制,以及解决进程间资源竞争所引发的死锁问题。
二、实验介绍:哲学家就餐问题是由荷兰计算机科学家伊克斯特拉(Dijkstra)于1965年首次提出的。
其问题描述如下:五位哲学家坐在一张圆桌子周围,每个哲学家面前有一碗饭和一根筷子。
哲学家的生活方式是交替地进行思考和进食。
当一个哲学家思考时,他不需要使用他的两个筷子;当一个哲学家想吃饭时,他需要同时获取他的左右两个筷子,并在获取到筷子后才能开始进食。
问题的关键是如何解决哲学家间的筷子竞争问题,以及避免死锁的发生。
三、实验设计:1.并发思路每个哲学家作为一个进程,在进行思考和进食这两个操作之前,需要获取他的两个筷子。
接下来考虑进程同步的两个关键点:-互斥:保证每个筷子同时只能被一个哲学家使用,避免资源竞争问题。
-死锁避免:通过限制只允许至多四位哲学家同时持有筷子,从而避免死锁发生。
2.进程同步机制- 互斥:使用Semaphore实现互斥,每个筷子都是一个Semaphore,初始值为1-死锁避免:引入一个全局计数器,记录当前持有筷子的哲学家数量,每次哲学家想要获取筷子时,先检查该计数器,仅当计数器小于4时才会获取筷子。
四、实验步骤:1.创建5个哲学家进程和5个筷子线程。
2.每个哲学家的线程循环执行思考和进食操作。
3.在进食之前,哲学家需要获取两个筷子,获取筷子的顺序按照哲学家编号进行,每个哲学家先获取自己的左边筷子,再获取自己的右边筷子。
4.进行进食操作后,哲学家释放两个筷子。
5.循环执行步骤3和步骤4,直到实验结束。
五、实验结果:通过观察实验结果,可以看到哲学家的思考和进食操作交替进行,并且避免了死锁的发生。
六、实验总结:通过本次实验,我了解了操作系统中的进程同步机制,并学会了如何解决资源竞争和死锁问题。
在本实验中,我使用了Semaphore和全局计数器实现了互斥和死锁避免,从而成功模拟了哲学家就餐问题。
哲学家就餐问题的算法实现
哲学家就餐问题的算法实现哲学家就餐问题是一个经典的并发计算问题,描述了五个哲学家围坐在一张圆桌前,每个人面前有一碟食物,并且每两个哲学家之间共享一只叉子。
每个哲学家可以执行两个操作:思考和就餐。
当一个哲学家就餐时,他需要同时拿起他的左右两只叉子,并且在就餐完毕后放下叉子。
这个问题的难点在于如何解决可能出现的死锁情况,即每个哲学家都拿起了自己左边的叉子,然后都在等待右边的叉子。
为了避免死锁,需要设计一个算法来保证每个哲学家都能够正确地就餐。
以下是一个可能的解决方案,称为"资源分级"算法:1. 为每个哲学家设计一个状态变量,并初始化为"思考"状态。
2. 每个叉子也有一个状态变量,初始状态为"可用"。
3. 当一个哲学家想要就餐时,他必须拿起他的左右两只叉子。
但是如果有一只或两只叉子已经被其他哲学家持有,他必须等待。
4. 当一个哲学家拿起了他的左右两只叉子时,他可以开始就餐,并将状态变量更新为"就餐"状态。
5. 当一个哲学家就餐完毕后,他将叉子放回桌子上,并将状态变量更新为"思考"状态。
6. 如果一个哲学家发现无法同时拿到他的左右两只叉子,他需要先放下已经持有的叉子,并将状态变量更新为"等待"状态。
然后他等待其他哲学家释放叉子的资源,并尝试再次拿起他的左右两只叉子。
以上是一个简单的"资源分级"算法,可以避免死锁的发生。
但是这个算法可能会导致一些哲学家始终处于等待状态,无法实现公平性。
为了解决这个问题,可以使用更复杂的算法,如Chandy/Misra解法或Dijkstra解法,这些算法可以实现更公平的资源分配。
总结起来,哲学家就餐问题是一个经典的并发计算问题,可能会引发死锁情况。
通过设计合理的算法,如"资源分级"算法或更复杂的解法,可以解决这个问题并保证公平性。
实验四模拟“五个哲学家”问题
实验四模拟"五个哲学家"问题魏陈强学号:23020092204168谢思发学号:23020092204174一、实验题目:哲学家就餐问题是一种典型的同步问题,它是由Dijkstra提出并解决的。
该问题描述如下:有五个哲学家围坐在一张圆形餐桌,交替做以下两件事:吃饭和思考。
餐桌中间有一碗意大利面,每两个哲学家之间只有一支餐叉,如果他们想吃面则必须使用其左右的两支餐叉。
显然每次最多只能有2个哲学家同时进餐,而且进餐过程有可能会产生死锁,如每个哲学家都拿着左手餐叉,等待右手餐叉。
从而导致五个哲学家无法进餐而饿死。
现需实验模拟解决哲学家进餐问题,使哲学家们能顺利的进餐思考。
二、算法分析:该实验的要点是,解决并发环境下,多进程之间的同步与互斥问题。
进程间的同步互斥必然涉及进程间通信。
但是进程的内存空间是彼此隔离的,因此它们之间的通信只能通过如下手段:IPC机制、管道、信号或文件。
本次实验采用文件手段解决通信问题。
经验证如果哲学家中同时存在左撇子和右撇子,则哲学家问题有解。
模拟程序的框架如下所示:定义5个文件,分别表示5个叉子。
其文件名按如下方式说明:Static char* forks[5]={"fork0","fork1","fork2","fork3","fork4"};哲学家的行为可以用如下函数描述:Void philosopher(int i){while(1){thinking(i,nsecs);TakeFork(i);eating(i,nsecs);putFork(i);}}在主程序里,可以用以下的程序段生成5个哲学家进程:#define N 5for(i=0;i<N;i++){pid=fork();If(pid==0)philosopher(i);}wait(NULL);拿起叉子可以如此定义:void takeFork(i){if(i==N-1){lock(forks[0]);lock(forks[i]);else {lock(forks[i]);lock(forks[i+1]);}}放下叉子可以如此定义:void putFork(i){if(i==N-1){unclolck(forks[0]);unlock(forks[i]);}else{unlock(forks[i]);unlock(forks[i+1]);}}三、详细代码#include "apue.h"#include <sys/wait.h>#include <string.h>#include "lock.h"#include <stdlib.h>#define N 5int main(int argc,char *argv[]){int time,i;pid_t pid[5];static char* forks[5] = {"fork0","fork1","fork2", "fork3", "fork4"}; if(argc==2)time=atoi(argv[1]);elseerr_sys("error!");for(i=0;i<N;i++)unlock(forks[i]);for(i = 0; i < N; i++){pid[i] = fork();if( pid[i] == 0 ){while(1){printf("The %d philosopher is thinking\n",i);sleep(time);if( i == N - 1 ){lock( forks[0] );lock( forks[i] );}else{lock( forks[i] );lock( forks[i + 1] );}printf("The %d philosopher is eating\n",i);sleep(time);if( i == N - 1 ){unlock( forks[0] );unlock( forks[i] );}else{unlock( forks[i] );unlock( forks[i + 1] );}}}// if(waitpid(pid[i],NULL,0)!=pid[i])// err_sys("waitpid error");}wait(NULL);exit(0);}四、实验结果四、心得体会:这次实验总体来说偏难,整个过程不太顺利。
哲学家吃饭问题 实验报告 操作系统
欢迎共阅目录1.设计题目与要求 (2)1.1设计目的1.2设计要求2.总体设计思想与相关知识 (2)2.1总体设计思想2.2问题描述2.3解决方案3.数据结构、流程图 (2)3.1数据结构3.2流程图4.源代码 (3)5.运行结果 (6)6.结果分析 (7)7.总结及心得体会 (7)1.设计题目与要求1.1设计目的掌握进程同步问题的解决思路及方法,熟练使用Windows操作系统提供的信号量机制解决各种进程同步问题。
1.2设计要求设有五个哲学家,共用一张放有五把椅子的餐桌,每人坐在一把椅子上,桌子上有五个碗和五只筷子,每人两边各放一只筷子。
哲学家们是交替思考和进餐,饥饿时便试图取其左右最靠近他的筷子。
条件:(1) 只有拿到两只筷子时,哲学家才能吃饭。
(2) 如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。
(3) 任意一个哲学家在自己未拿到两只筷子吃饭前,不会放下手中拿到的筷子。
2.总体设计思想与相关知识2.1总体设计思想哲学家的生活就是思考和吃饭,即思考,饿了就餐,再思考,循环往复。
要求是:每一个哲学家只有在拿到位于他左右的筷子后,才能够就餐;哲学家只能先拿左边的筷子,再去拿右边的筷子,而不能同时去抓他两边的筷子,也不能从其他哲学家手中抢夺筷子;哲学家每次就餐后必须放下他手中的两把筷子后恢复思考,不能强抓住餐具不放。
设计一个程序,能够显示当前各哲学家的状态和桌上餐具的使用情况,并能无死锁的推算出下一状态各哲学家的状态和桌上餐具的使用情况。
即设计一个能安排哲学家正常生活的程序。
2.2问题描述可能出现死锁问题,因为当五个哲学家都饥饿时,都拿着一支筷子,这样就可能五个哲学家都用不上餐。
2.3解决方案2.3.1 最多允许4个哲学家同时坐在桌子周围。
2.3.2 给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之。
2.3.3 为了避免死锁,把哲学家分为三种状态,思考,饥饿,进食,仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子,并且一次拿到两只筷子,否则不拿。
哲学家就餐问题(进程管理)
进程管理一、设计目的、功能与要求设计目的:掌握进程管理的相关内容,对进程的同步和互斥,及信号量机制有深入的理解实验内容:模拟实现用信号量机制解决哲学家就餐问题具体要求:任选一种计算机高级语言编程实现实现5个哲学家(5只筷子)的顺利就餐需避免出现死锁使用信号量、及信号量的等待队列使用P操作、V操作能够显示每个哲学家、及每只筷子的状态二、问题的详细描述、需求分析该实验要求模拟实现用信号量机制解决哲学家就餐问题。
哲学家就餐问题详细描述如下:有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子,即共5只筷子。
每个哲学家的行为是思考和进餐。
每个哲学家的行为是思考和进餐。
为了进餐,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。
思考时则同时将两支筷子放回原处时则同时将两支筷子放回原处。
规则:只有拿到两只筷子时,哲学家才能吃饭;只有拿到两只筷子时,哲学家才能吃饭;如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;任何一个哲学家在自己没有拿到两只筷子吃饭之前,决不放下自己手中的筷子。
为了解决哲学家就餐问题同时解决死锁现象,需要设计一定的解决策略。
有这样几种解决办法:1.至多只允许四个哲学家同时进餐,以保证至少有一个哲学家可以进餐,最终总会释放出他所用过的两只筷子,从而可使更多的哲学家进餐;2.仅当左右两只筷子均可用时,才允许哲学家拿起筷子就餐;3.规定奇数号哲学家先拿起右边筷子,然后再去拿左边筷子,而偶数号哲学家则相反。
该实验我采取了第2种解决方案,每个哲学家在确定自己左右两边的筷子都能用时,才能同时拿起两只筷子进餐,进餐完成后同时放下两只筷子。
三、数据结构、功能设计(功能与框图、功能模块说明)该实验使用java的多线程,同时利用到关键字synchronized实现了共享数据的互斥锁定,以保证每只筷子的状态的互斥的。
6个哲学家进餐问题预防死锁
红河学院课程设计报告操作系统课程名称:6个哲学家进餐设计题目:院系:工学院专业:计算机科学与技术班级:11计科班曹永前设计者:学号:201101030466指导教师:韦相2013 年 5 月26 日1. 问题描述:一个房间内有6个哲学家,他们的生活就是思考和进食。
哲学家思考后,过一定的时间就会饥饿,饥饿之后就想吃饭,吃饭后再思考。
房间里有一张圆桌,桌子周围放有五把椅子,分别属于五位哲学家每两位哲学家之间有一把叉子,哲学家进食时必须同时使用左右两把叉子。
2. 问题分析1、写出哲学家进餐的算法描述。
用六只筷子解决需要用两双筷子来进餐的六个哲学家,由于每个哲学家都需要其周围的两只筷子,所以筷子是公用信号量,这久需要设置一个互斥信号量,来使六个哲学家互斥的进餐.具体做法将六个信号量设置为0-5,用pv 源于来控制信号量,并将六个哲学家分别编号为0-5.经过仔细分析我们会发现,有这样一个问题存在,就是当每个哲学家都申请到他周围的一只筷子时,由于他们每人都只有一只筷子无法进餐,没有进餐他们就无法释放他们已经得得到的筷子,这样是进餐出于一种僵局,无法继续下去,这就是死锁问题.2、死锁问题的分析与具体的解决方法。
死锁问题就是当每个哲学家都拿到且只拿到一只筷子,这样每个哲学家都无法进餐,也无法释放所得到的筷子,所以解决死锁我们就要从这入手,就是怎样去预防使所有哲学家不要同时去申请他们同一方向的筷子.根据这解决死锁的方法有以下几种:a.每一次最多只能有五个哲学家申请进餐.这样其中的一个哲学家就能申请到两只筷子,就能够进餐,再将筷子释放给其他哲学家进餐.b.用AND信号量,就是哲学家需同时申请其左右两边的筷子,两边都有资源的时候,才能让这个哲学家得到资源,这样哲学家只要申请到筷子就能进餐, 再将筷子释放给其他哲学家进餐.c.用管程机制来实现。
d.我们前面已经将每个哲学家都分配了一个编号,我们可以编号为奇数的哲学家首先去申请其左边的筷子,再去申请其右手边的筷子;让编号为偶数的哲学家,先去申请其右边的筷子,再去申请其左边的筷子.我们可以看出编号为奇数的哲学家左边,与编号为偶数的哲学家的右边为同一只筷子,当其中一个哲学家拿到此筷子后,他另一边的筷子也是空闲的,这样就能避免死锁.主程序中我使用的是最后一种避免死锁的方法.3、用C程序实现哲学家进餐。
哲学家就餐问题的算法实现
哲学家就餐问题的算法实现在哲学家就餐问题中,假定有五位哲学家围坐在一张圆桌旁,每位哲学家面前都放着一碗意面和一把叉子。
这五位哲学家中的每位都有两种活动,一种是思考,一种是就餐。
但是,这五位哲学家只有五支叉子共用,也就是说,每个哲学家只能在自己左右两边分别拿起一把叉子。
若这五位哲学家中有若干人同时拿着左手边的叉子,或者同时拿着右手边的叉子,那么他们都无法就餐。
这时,就需要找到一种算法来解决这个问题。
解法一:Chandy/Misra解法Chandy/Misra解法是一种分布式算法,它的思路是使得每一位哲学家都向右边的人要叉子。
一旦它们都拿到了右边的叉子,就会开始就餐,然后把左右两个叉子都放回去。
这种算法的优点是它具有分布式系统的特点,不会造成资源竞争,而且在算法处理结束后,所有人都不会处于饥饿状态。
但是,这种算法实现的难度比较大,因为需要每个哲学家都向右边的人要叉子,而且需要考虑异常情况。
解法二:Dijkstra解法Dijkstra解法也被称为银行家算法,它的思路是让每一位哲学家先拿一支叉子,只有拿到两支叉子后,才可以开始就餐。
一旦就餐结束,哲学家就将叉子放回去。
这种算法的优点是它比较简单,易于实现。
但是,如果有一位哲学家先拿了一支叉子并且不再释放,那么其他哲学家就会陷入死锁状态。
解法三:Semaphore解法Semaphore解法是以信号量为基础的算法,它的思路是对每支叉子定义一个信号量,并使用信号量来控制哲学家与叉子之间的关系。
一旦一个哲学家想要就餐,就需要请求两个叉子的信号量,如果请求不到,则会被阻塞。
这种算法的优点是它具有可扩展性,而且可以支持多个进程同时使用资源。
但是,它比较复杂,可能会导致死锁。
结论在实际开发中,我们可以根据自己的需求选择合适的算法来解决哲学家就餐问题。
如果要求系统具有分布式系统的特点,可以使用Chandy/Misra解法;如果要求简单易行和易于实现,可以使用Dijkstra解法;如果要求可扩展性和支持多进程,可以选择Semaphore解法。
哲学家就餐问题报告
哲学家就餐问题报告一、实验目的1、熟练使用VC6、0编译环境,调试并正确运行程序。
2、理解哲学家就餐问题中出现的问题,进而掌握死锁的必要条件。
3、理解源程序中产生和防止死锁的算法,及相关窗口操作。
4、熟悉哲学家就餐问题流程并写出其伪代码二、实验内容有五个哲学家围坐在一圆桌旁(如图1),桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子。
每个哲学家的行为是思考,感到饥饿,然后吃通心粉。
为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。
图1 图2三、实验要求1、程序需有防止死锁发生采取的措施;2、程序要有产生死锁的分配方式;四、实验算法实现1、不发生死锁的方式由源码gChopstickState[iLeftChopstick] = iPhilosopher; gChopstickState[iRightChopstick] = iPhilosopher;知基本思路是要么一下子占用两支筷子要么不占用,先确定两只筷子均没被占用才获取筷子,这样就打破了死锁的必要条件。
伪代码如下; var mutexleftchopstick,mutexrightchopstick; beging: resting; waiting; p(mutexleftchopstick); //先改变左手筷子信号量 p(mutexrightchopstick); //马上改变右手筷子信号量GetResource(leftchopstick,rightchopstick); //同时占用左右手筷子 eating; v(mutexleftchopstick); //释放资源v(mutexrightchopstick); end2、发生死锁的方式基本思路是有筷子即占用,看似效率很高,但因为资源有限,且不可抢占,很容易发生死锁。
源码理解: gDinerState[iPhilosopher] = WAITING;//wants chopsticks result = WaitForSingleObject(gchopStick[iLeftChopstick], INFINITE); gChopstickState[iLeftChopstick] = iPhilosopher; //得到左手筷子 Sleep(P_DELAY/4); //休眠状态gDinerState[iPhilosopher] = WAITING; //继续等待另一只手筷子 result =WaitForSingleObject(gchopStick[iRightChopstick], INFINITE); gChopstickState[iRightChopstick] = iPhilosopher; //直到等到右手筷子伪码书写:var mutexleftchopstick,mutexrightchopstick; beging: resting; waiting; p(mutexleftchopstick); //改变左手筷子信号量GetResource(leftchopstick); //获取左手筷子p(mutexrightchopstick); //改变右手筷子信号量GetResource(rightchopstick); //获取右手筷子 eating;v(mutexleftchopstick); v(mutexrightchopstick); end五、实验运行结果程序界面说明:通过位图句柄画演示的界面1.先画桌子,再画筷子,再画盘子,2.再画哲学家:哲学家用圆表示,根据哲学家的状态选择画笔(为resting 状态时为绿色圆圈,为等待或者,就餐时为红色圆圈)3.最后画哲学家的手:判断的依据是若筷子的编号和哲学家的编号一直致,那么认为这根筷子属于这个哲学家(筷子资源空闲)那么可以画手表示哲学家获得了这个筷子。
操作系统哲学家就餐问题实验报告
操作系统哲学家就餐问题实验报告实验目的:通过实验探究操作系统中的哲学家就餐问题,了解并掌握解决该问题的不同算法。
实验原理:哲学家就餐问题是一个典型的并发控制问题,该问题描述了一群哲学家围坐在圆桌上,每个哲学家左右两边各有一只筷子,哲学家只有同时拿到左右两只筷子时才能进餐,进餐完毕后将筷子放回桌面。
该问题的解决涉及到互斥、死锁、饥饿等并发问题。
实验步骤:1. 实现基于信号量的解法:- 为每个哲学家和筷子创建一个信号量;- 哲学家进入就餐前先检查左右两只筷子是否可用;- 若可用,则将左右两只筷子设置为不可用,并进餐;- 进餐完毕后将左右两只筷子设置为可用。
2. 实现基于管程的解法:- 哲学家类中定义进餐和放下筷子的方法;- 使用一个互斥锁来确保每次只有一个哲学家能进入管程;- 当某个哲学家想要进餐时,先检查是否有足够的筷子可用;- 若可用,则进入进餐方法,将筷子设置为不可用,并开始进餐; - 进餐完毕后,释放筷子并通知其他哲学家。
3. 运行实验程序,观察哲学家的就餐过程。
4. 分析实验结果,比较两种算法的优缺点。
实验结果与分析:通过观察实验程序运行的结果,可以发现在基于信号量的解法中,哲学家的就餐过程是以并发的方式进行的,每个哲学家在不产生死锁的前提下获取到筷子并进餐。
但是,由于每个哲学家只能同时拿到一只筷子,有可能会出现饥饿的情况,即某个哲学家一直无法获取到筷子进餐。
而基于管程的解法则能够避免饥饿的问题,每个哲学家在进餐前都会检查是否有足够的筷子可用,若不可用则等待。
通过互斥锁的使用,确保每次只有一个哲学家能够进入管程进行操作,避免了并发产生的问题。
综上所述,基于管程的解法相对于基于信号量的解法更加可靠,能够避免饥饿问题的出现。
但是在实际应用中,两种解法的选择还需要根据具体情况进行权衡和取舍。
操作体统实验报告
中山大学南方学院实验报告课目:操作系统姓名:陈瑞全班级:08级电子一班指导老师:梁路哲学家就餐问题一、实验题目:解决五个哲学家就餐问题二、设计内容:三、开发环境:四、分析设计:1.给五个哲学家编号为1,2,3,4,5;产生一个1~5之间的随机数,规定一次产生两个哲学家;2.设置一个全局变量,将上一次产生的信号量纪录在内,并判断此次与上次的编号是否相差2或3;若是,即可同时吃,并释放上一个哲学家的筷子,若不是,只释放上一个哲学家的筷子。
3.作N次循环(N自己输入)五个哲学家围坐在一圆桌旁,桌中央有一盘菜,每人面前有一只空盘子,每两人之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃菜.为了吃菜每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子#define N 5void philosopher (int i){while (true){思考;取fork[i]; 取fork[(i+1) % 5];进食;放fork[i]; 放fork[(i+1) % 5];}}为防止死锁发生可采取的措施:最多允许4个哲学家同时坐在桌子周围仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子()给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之为了避免死锁,把哲学家分为三种状态,思考,饥饿,进食,并且一次拿到两只筷子,否则不拿.哲学家就餐问题解法(1)#define N 5void philosopher (int i){while (true){思考;取fork[i]; 取fork[(i+1) % 5];进食;放fork[i]; 放fork[(i+1) % 5];}}哲学家就餐问题解法(2)#define N 5#define THINKING 0#define HUNGRY 1#define EATING 2#typedef int semaphore;int state[N];semaphore mutex=1;semaphore s[N];void test(int i){if (state[ i ] == HUNGRY)&& (state [ (i-1) % 5] != EATING)&& (state [ (i+1) % 5] != EATING){state[ i ] = EATING;V(&s[ i ]);}}void philosopher (int i){ while (true){思考;P(&mutex);state[i] = HUNGRY;test(i);V(&mutex);P(&s[i]);拿左筷子;拿右筷子;进食;放左筷子; 放右筷子;P(&mutex)state[ i ] = THINKING;test([i-1] % 5);test([i+1] % 5);V(&mutex);}}state[ i ] = THINKINGs[ i ] = 0为每个哲学家使用POSIX线程(pthread)建立独立的线程(有独立的id),用互斥(叉子其他哲学家使用时,另一个哲学家不能使用)和条件(哲学家饿了才尝试去得到叉子,得到相邻的左右两把叉子才能进餐)来分到叉子。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南昌大学实验报告
学生姓名:倪焕学号:8000114018 专业班级:软件工程141班
实验类型:■验证□综合□设计□创新实验日期:2016.5.24 实验成绩:
一、实验项目名称
哲学家就餐问题
二、实验目的
利用PV操作解决哲学家就餐问题
三、软硬件环境
软件:Visual Studio2010
硬件:PC机一台
四、实验内容结果
//哲学家就餐问题的解法
#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std; //命名空间std内定义的所有标识符都有效
const unsigned int PHILOSOPHER_NUM=5; //哲学家数目
const char THINKING=1; /*标记当前哲学家的状态,1表示等待,2表示得到饥饿,3表示正在吃饭*/
const char HUNGRY=2;
const char DINING=3;
HANDLE hPhilosopher[5]; //定义数组存放哲学家
/*HANDLE(句柄)是windows操作系统中的一个概念。
指的是一个核心对象在某一个进程中的唯一索引*/
HANDLE semaphore[PHILOSOPHER_NUM]; // semaphore 用来表示筷子是否可用
HANDLE mutex; // Mutex用来控制安全输出
DWORD WINAPI philosopherProc( LPVOID lpParameter) //返回DWORD(32位数据)的API 函数philosopherProc
{
int myid; //哲学家id
char idStr[128];
char stateStr[128];
char mystate;
int ret;
unsigned int leftFork; //左筷子
unsigned int rightFork; //右筷子
myid = int(lpParameter);
itoa(myid, idStr, 10);
WaitForSingleObject(mutex, INFINITE);
cerr << "philosopher " << myid << " begin......" << endl;
ReleaseMutex(mutex);
mystate = THINKING; //初始状态为THINKING leftFork = (myid) % PHILOSOPHER_NUM;
rightFork = (myid + 1) % PHILOSOPHER_NUM;
while (true)
{
switch(mystate)
{
case THINKING:
mystate = HUNGRY; // 改变状态
strcpy(stateStr, "HUNGRY");
break;
case HUNGRY:
strcpy(stateStr, "HUNGRY");
ret = WaitForSingleObject(semaphore[leftFork], 0); // 先检查左筷子是否可用
if (ret == W AIT_OBJECT_0)
{
ret = WaitForSingleObject(semaphore[rightFork], 0); //左筷子可用就拿起,再检查右筷子是否可用
if (ret == WAIT_OBJECT_0)
{
mystate = DINING; // 右筷子可用,就改变自己的状态
strcpy(stateStr, "DINING");
}
else
{
ReleaseSemaphore(semaphore[leftFork], 1, NULL); // 如果右筷子不可用,就把左筷子放下
}
}
break;
case DINING:
// 吃完后把两支筷子都放下
ReleaseSemaphore(semaphore[leftFork], 1, NULL);
ReleaseSemaphore(semaphore[rightFork], 1, NULL);
mystate = THINKING; // 改变自己的状态
strcpy(stateStr, "THINKING");
break;
}
// 输出状态
WaitForSingleObject(mutex, INFINITE);
cerr << "philosopher " << myid << " is : " << stateStr << endl;
ReleaseMutex(mutex);
Sleep(5000);
}
}
int main()
{
int i,run;
run = 1;
mutex = CreateMutex(NULL, false, NULL);
for (i=0; i<PHILOSOPHER_NUM; i++)
{
semaphore[i] = CreateSemaphore(NULL, 1, 1, NULL); //创建一个新的信号量
hPhilosopher[i]=CreateThread(NULL,0,philosopherProc,LPVOID(i),
CREATE_SUSPENDED,0); //创建一个新线程
ResumeThread(hPhilosopher[i]); //线程恢复函数
Sleep(15);
}
while(run){
Sleep(5000);
cerr<<"**************************************"<<endl;
}
return 0; }
五、实验体会
通过本次实验,首先是对哲学家就餐问题有了更深的了解,而通过PV操作,很好的解决了哲学家就餐问题,这使得我对PV操作更加熟悉,同时帮助我理解了原先不太懂的地方,希望强加练习。