操作系统实验报告哲学家就餐
操作系统实验报告(哲学家问题)
操作系统实验报告实验者:朱毅学号:0701013 实验题目:哲学家问题设有5个哲学家,共享一张放有5把椅子的桌子,每人分得一把椅子。
但是,桌子上总共只有5支筷子,在每人两边分开各放一支。
哲学家们在肚子饥饿时才试图分两次从两边拾起筷子就餐。
条件:(1)只有拿到两支筷子时,哲学家才能吃饭。
(2)如果筷子已在他人手上,则哲学家必须等他人吃完之后才能拿到筷子。
(3)任一哲学家在自己未拿到两支筷子吃饭之前,决不放下自己手中的筷子。
试:(1)描述一个保证不会出现两个邻座同时要求吃饭的通信算法。
(2)描述一个既没有两邻座同时吃饭,又没有人饿死(永远拿不到筷子)的算法。
(3)在什么情况下,5个哲学家全部吃不上饭?开发环境:Microsoft V isual Foxpro 6.0算法描述:数据环境:表KUAIZI 相应字段:筷子号状态(逻辑型)使用者桌号表ZHEXUEJIA相应字段:哲学家名所属状态拥有左筷子(逻辑型)拥有右筷子(逻辑型)桌号表FANGAN 相应字段方案表的具体内容请参见DAIMA.DOC文件本程序解决死锁的关键:从苏格拉底开始往黑格尔依次处理,对每人的处理一次进行到底,从而肯定必然有一人完全占有资源,避免了死锁,其实质就是按照5个哲学家的座位号作为绝对的优先级进行资源的先后分配。
初始状态:选择算法(以下两算法不同之处用黑体标识)算法一:(1)保证不会出现两个邻座同时要求吃饭的通信算法。
1、由操作人员按“有人饿了”按钮,控制是否有哲学家肚子饿了。
2、出现复选框和“确定”按钮,挑选哲学家后,按“确定”后确认选择。
当做出一个选择后,该哲学家左右两边的哲学家则不能被选中(通过对复选框的ENABLED属性控制),若取消选中,则该哲学家左右两边的哲学家(在该哲学家的另一邻居也未被选中为前提) 还原为可选状态。
3、“确认”后执行以下步骤:①从苏格拉底到黑格尔依次检验其是否是此次被选中②若是此次被选中,进行以下步骤:a 改变表KUAIZI 和表ZHEXUEJIA中相应的字段:ZHEXUEJIA:所属状态由F(Full)改为H(Hungry)b执行PROG1,分配给这些饥饿的哲学家筷子,若左边有筷子,取之,并标识“拥有左筷子”;若右边有筷子,取之,并标识“拥有右筷子”。
实验4 哲学家就餐问题的实现
• 优先级: Task0>Task1>Task2>Task3>Байду номын сангаасask4
嵌入式操作系统实验
实验4 哲学家就餐问题的实现
什么是哲学家就餐问题 本实验目的 实验内容
void Task (void *pdata) { …… for (;;) { /* 无限循环 */ TASK_Thinking_To_Hungry(i);
OSSemPend(fork[i], 0, &err); OSSemPend(fork[j], 0, &err);
TASK_Eat(i); OSSemPost(fork[j]); OSSemPost(fork[i]); OSTimeDly(200); } }
/* Acquire semaphores to eat */
嵌入式操作系统实验
实验4 哲学家就餐问题的实现
什么是哲学家就餐问题 本实验设计
互斥问题
嵌入式操作系统实验
实验4 哲学家就餐问题的实现
什么是哲学家就餐问题 本实验目的
目的
通过经典的哲学家就餐实验,了解如何利用信号量对 共享资源进行互斥访问。
• 5个任务:Task0、Task1、 Task2、 Task3、 Task4
/* Release semaphore /* Delay 100 clock tick
*/ */
嵌入式操作系统实验
实验4
哲学家就餐问题的实现
什么是哲学家就餐问题 本实验目的 实验内容 实验要求
实验要求
1. 调试代码,运行结果截图 2. 将p51的OSSemPost(fork[j]); OSSemPost(fork[i]); 顺序改变下,运行结果有变化?
操作系统哲学家进餐问题
操作系统实习报告一、设计目的:死锁是进程并发执行过程中可能出现的现象,所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局。
哲学家就餐问题是描述死锁的经典例子。
为了防止死锁,可以采用资源预分配法或者资源按序分配法。
资源预分配法是指进程在运行前一次性地向系统申请它所需要的全部资源,如果系统当前不能够满足进程的全部资源请求,则不分配资源, 此进程暂不投入运行,如果系统当前能够满足进程的全部资源请求, 则一次性地将所申请的资源全部分配给申请进程。
二、设计内容哲学家进餐问题的模拟。
三、开发环境windows环境,Myeclipse平台。
四、分析设计<一>实验原理哲学家进餐问题描述的是五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五只碗和五只筷子。
他们的生活方式是交替地进行思考和进餐。
平时,一个哲学家进行思考,饥饿时便试图取用其左右的最靠近他的筷子,只有在他拿到两只筷子时才能进餐。
进餐完毕放下筷子继续思考。
由于:①只有拿到两只筷子时,哲学家才能吃饭;②如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;③任何一个哲学家在自己没有拿到两只筷子吃饭之前,决不放下自己手中的筷子。
则可能出现五个哲学家都饥饿时都拿着一直筷子。
这样就可能五个哲学家都用不上餐。
该问题可用记录型信号量解决,经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥使用,可以用一个信号量表示一只筷子,由这五个信号量组成信号量数组。
当哲学家饥饿时总是先拿其左边的筷子,成功后,再去拿右边的筷子,又成功后方可就餐。
进餐完,又先放下他左边的筷子,再放下右边筷子。
这个算法可以保证不会有两个相邻的哲学家同时就餐,但有可能引起死锁。
对于死锁问题可采取这样的几种解决方法:(1)至多只允许四个哲学家同时进餐,以保证至少有一个哲学家可以进餐,最终总会释放出他所用过的两只筷子,从而可使更多的哲学家进餐;(2)仅当左右两只筷子均可用时,才允许哲学家拿起筷子就餐(3)规定奇数号哲学家先拿起右边筷子,然后再去拿左边筷子,而偶数号哲学家则相反。
操作系统哲学家问题实验报告
实验报告三实验名称:一、调试验证“有限缓冲”经典同步问题二、利用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)问题分析当出现以下情形,在某一瞬间,所有的哲学家都同时启用这个算法,拿起左侧的筷子,而看到右侧筷子都不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此永远重复下去。
对于这种情况,所有的程序都在运行,但却都无法取得进展,即出现饿死,所有的哲学家都吃不上饭。
解决死锁问题:为了避免死锁,把哲学家分为三种状态:思考,饥饿(等待),进食,并且一次拿起两只筷子,否则不拿。
操作系统课程设计——哲学家进餐问题
操作系统课程设计——哲学家进餐问题1000字哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着广泛的应用。
因此,在操作系统课程设计中,探究哲学家进餐问题是一件非常有意义的事情。
哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。
每个哲学家有两种状态:思考和进餐。
当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这两只筷子,进入思考状态。
在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法拿到右手边的筷子,导致无法进餐。
因此,需要在代码中实现同步互斥机制,避免死锁的发生。
本课程设计中,我使用了Java语言来实现哲学家进餐问题。
在代码实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来模拟哲学家的思考和进餐过程。
为了避免死锁,我使用了Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。
同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等待下一个机会。
在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。
每个筷子都是一个二元信号量,初始为1,表示可用。
当一个哲学家拿起筷子时,他会将对应的信号量减1,表示不可用。
当哲学家用完筷子之后,会将对应的信号量加1,表示可用。
通过这种方式,实现了对筷子的访问同步。
最后,我对代码进行了测试,模拟了多位哲学家同时进行进餐的过程。
在测试中,我发现哲学家进餐的速度受到筷子的数量和哲学家思考进餐比例的影响。
当筷子数量少于哲学家数量时,容易出现死锁;当哲学家思考和进餐的时间相当时,程序的运行情况比较稳定。
总的来说,本课程设计实现了哲学家进餐问题,通过学习该问题,我更深入地理解了同步互斥机制的重要性,并学会了如何使用信号量来实现同步互斥。
哲学家吃饭问题试验报告操作系统
目录1.设计题目与要求21.1设计目的1.2设计要求2.总体设计思想与相关知识22.1总体设计思想2.2问题描述2.3解决方案3.数据结构、流程图23.1数据结构3.2流程图4.源代码.35.运行结果.66.结果分析.77.总结及心得体会.71.设计题目与要求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为了防止死锁,把哲学家分为三种状态,思考,饥饿,进食,仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子,并且一次拿到两只筷子,否那么不拿.3.数据结构及流程图3.1数〞结构philosopherProc+myid:int+mystate:int+philosopherProc(LPVOIDlpParameter)+ResumeThread(hPhilosopher[i]):int +strcpy(stateStr, ""):int程序中定义一个哲学家类,包含两个私有对象和四个公有对象.myid对象:报讯哲学家的编号.mystate对象:用于保存当前该哲学家的状态,philosopherProc( LPVOID lpParameter) 方法:哲学家类构造函数,PHILOSOPHER_NUM表示哲学家编号ResumeThread(hPhilosopher[i]) 方法:返回该哲学家编号strcpy(stateStr,"") 方法:返回哲学家当前状态根据题目要求改变哲学家的状态(饥饿 ,进餐,思考,饥饿)3.2流程图的一个概念.指的是一个核心对象在某一个进程中的唯一索引*/HANDLE semaphore[PHILOSOPHER_NUM]; // semaphore 用来表示筷子是否可用4. 源代码〔c++〕//哲学家就餐问题的解法 #include <windows.h> #include <process.h> #include <time.h> #include <stdlib.h> #include <stdio.h> #include <iostream> using namespace std;有效//命名空间std 内定义的所有标识符都 const unsigned int PHILOSOPHER_NUM=5; //const char THINKING=1;表示得到饥饿,3表示正在吃饭*/ const char HUNGRY=2; const char DINING=3; HANDLE hPhilosopher[5];/*///*HANDLE 〔 哲学家数目标记当前哲学家的状态,1表示等待,2定义数组存放哲学家句柄〕是windows 操作系统中DWORD WINAPI philosopherProc( LPVOID IpParameter) // 据)的API函数philosopherProc {int myid;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);cout << "philosopher " << myid << " begin" << endl;ReleaseMutex(mutex);mystate = THINKING;//THINKINGHANDLE mutex;// Mutex 用来限制平安输出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 == WAIT_OBJECT_0){ret = WaitForSingleObject(semaphore[rightFork], 0); // 再检查右筷子是否可用if (ret == WAIT_OBJECT_0){mystate = DINING;//变自己的状态strcpy(stateStr, "DINING");)else{ReleaseSemaphore(semaphore[leftFork], 1, NULL); // 用,就把左筷子放下改变状态先检查左筷子是否左筷子可用就拿起,右筷子可用,就改如果右筷子不可返回DWORD32位数初始状态为)break;case DINING://吃完后把两支筷子都放下ReleaseSemaphore(semaphore[leftFork], 1, NULL);ReleaseSemaphore(semaphore[rightFork], 1, NULL);mystate = THINKING;//改变自己的状态strcpy(stateStr, "THINKING");break;)// 输出状态WaitForSingleObject(mutex, INFINITE);cout << "philosopher " << myid << " is : " << stateStr << endl;ReleaseMutex(mutex);// sleep a random time : between 1 - 5 sint sleepTime;sleepTime = 1 + (int)(5.0*rand()/(RAND_MAX+1.0));Sleep(sleepTime*10);))int main(){int i;srand(time(0));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);)for (i=0; i<PHILOSOPHER_NUM; i++)ResumeThread(hPhilosopher[i]);Sleep(2000);return 0;)5.运行结果6.结果分析对哲学家进行编号,将他们的初始状态全部设定为THINGKING接着先从0开始改变他们的状态为HUNGRY继续运行后4号和2号哲学家先DINING, 3号和1号哲学家为HUNGRY当4号哲学家吃完后,0号哲学家就开始DINING7.总结及心得体会这次操作系统的作业让我深刻的体会到操作系统的知识作用.培养我综合运用知识的水平,结合了C++的知识来解决这个问题.稳固了以前的知识.在设计这个程序的时候我遇到了很多困难,但是通过老师和同学们的帮助,我一一解决掉了.而且发现了我很多学习中的缺乏之处,对以前学习的知识熟悉不够深刻,掌握的不够,这个要好好复习一下.总的来说,这个操作系统的作业带给我很多收获,让我受益匪浅.封pliilcsopher.cpp附件:。
操作系统课程设计哲学家就餐问题
目录摘要 (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设计目的通过本次课设,对本学期的操作系统课程的学习理论知识的一次应用。
是理论结合实际的一次应用。
让我们学会对竞争资源的操作,控制,同时锻炼我们的编程水平。
使我们掌握多线程编程的方法;掌握MFC程序设计和API应用程序编程;培养我们基本控制程序的安全性及避免死锁的方法;培养我们分析、解决问题的能力;锻炼我们的自学能力;培养我们的组队合作能力;提高学生的科技论文写作能力。
1.2设计要求✧利用多线程编程模拟5个线程,竞争五个筷子去吃通心面;✧对临界资源的操作算法要简单易行;✧程序运行时不会产生死锁;✧对所设计的各模块系统进行调试;✧独立完成程序的设计与调试;✧设计好各个功能模块,合理安排他们的位置;✧程序结构清晰;✧程序界面友好直观。
2021年操作系统哲学家就餐问题实验报告
图3.返回哲学家状态步骤图图4返回餐具状态模块步骤图3)数据结构(1)、定义一个哲学家类, 包含两个私有对象和四个公有对象。
(2)、定义函数:Number对象: 哲学家编号;Status对象: 保留目前该哲学家状态, 0表示等候, 1表示吃饭, 2表示思索;Philosopher(int num)方法: 哲学家类结构函数, 参数num表示哲学家编号; find() const方法: 返回该哲学家编号;getinfo() const方法: 返回哲学家目前状态;Change()方法: 依据题目要求改变哲学家状态(等候->进餐->思索)另外, 程序中包含一个公有对象, bool类型数组tools[6], 用来保留6把餐具目前状态: true表示该餐具目前空闲, false表示该餐具目前正被使用。
程序中还包含两个公有函数: print和toolstatus。
Print用来返回一个哲学家状态, toolstatus用来返回一个餐具状态。
4)实现步骤1)打开VC, 选择菜单项File->New, 选择Projects选项卡并建立一个名为xwjwin32 console application工程, 创建时注意指定创建该工程目录;(2)在工程中创建源文件xwj.cpp: 选择菜单项Project->Add toproject->Files,此时将打开一个新窗口, 在其中“文件名”输入栏中输入自己想要创建文件名, 这里是xwj.cpp; 接着问询是否创建新文件时回复“yes”。
经过Workspace->Source Files打开该文件, 在其中编辑源文件并保留; (3)经过调用菜单项Build->Rebuild all进行编译连接, 能够在指定工程目录下得到debug->xwj.exe程序。
5、试验测试及分析:图5.测试结果1图7.测试结果3#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<<"筷子状态, 用表示使用中, 闲表示空闲中。
C++操作系统哲学家就餐问题课程设计报告
操作系统课程设计报告133301班20133481 杜闻播20133489 刘景凯20133494 裴硕2015年12月18日目录第一章引言 (1)第二章设计背景 (2)1.1 死锁 (2)1.2死锁产生的条件 (2)1.3 防止死锁 (2)1.3.1资源按序分配法 (3)1.3.2资源预分配法 (3)1.3 哲学家就餐问题 (3)第三章需求分析 (4)1.1 功能需求 (4)1.2 功能模块图 (4)第四章程序设计 (5)4.1 程序流程图 (5)4.2 模块设计 (5)4.3 模块实现 (6)4.3.1 死锁 (6)4.3.2 资源预分配 (7)4.3.3 资源按序分配 (7)第五章程序编码 (7)5.1 程序设计语言 (8)5.2 编程环境 (8)5.3 程序总体设计 (8)5.3.1 包结构设计 (8)5.3.2 总体设计思想 (8)第六章程序调试 (10)6.1 资源按序分配 (10)6.2 资源预分配 (11)6.3 死锁 (11)参考文献 (12)附录1 部分系统界面 (13)附录2 部分源程序 (14)第一章引言操作系统(Operating System,简称OS),是电子计算机系统中负责支撑应用程序运行环境以及用户操作环境的系统软件,同时也是计算机系统的核心与基石。
它的职责常包括对硬件的直接监管、对各种计算资源(如内存、处理器时间等)的管理、以及提供诸如作业管理之类的面向应用程序的服务等等。
死锁是进程并发执行过程中可能出现的现象,哲学家就餐问题是描述死锁的经典例子。
假设有几位哲学家围坐在一张餐桌旁,桌上有吃不尽的食品,每两位哲学家之间摆放着一根筷子,筷子的个数与哲学家的数量相等,每一位哲学家要么思考,要么等待,要么拿起左右两根筷子进餐。
本实验假设有五个哲学家和五根筷子,它们的编号都是从0到4。
如果每位哲学家都拿起左边的筷子,就会发生死锁。
为了防止死锁,可以采用资源预分配法或者资源按序分配法。
计算机系统实验报告(哲学家就餐死锁)
目录第一章总体设计 (3)1.程序结构设计第一章总体设计 (3)2. 程序设计组成框图………………………………………………………….错误!未定义书签。
3. 流程图……………………………………………………………………………错误!未定义书签。
第二章详细设计………………………………………………………………………………….错误!未定义书签。
1.功能说明 (5)2. 函数功能 (6)3.入口及出口参数说明 (6)4.函数调用关系描述 (7)第三章调试与测试 (8)第四章关键原程序清单和执行结果……………………………错误!未定义书签。
1.源程序…………………………………………………………………………….错误!未定义书签。
2.运行结果 (9)第五章参考资料 (9)第一章总体设计1. 程序结构设计程序需要六个线程,主线程用于显示主菜单,接收用户的功能选择;五个哲学家线程用于模拟哲学家的活动,即不停地思考、饥饿、进食。
相邻的两个哲学家线程需要共享他们中间的同一根筷子,因此对每一根筷子的使用要互斥,用互斥体数组h_mutex_chopsticks来实现。
主线程创建五个哲学家线程后要等待所有哲学家结束,用线程句柄数组h_thread来表示五个线程,主线程通过等待这五个线程句柄来实现同步。
该程序共有7个函数,这些函数可以分成4组。
各组包含的函数及其功能如图3-1所示。
2.程序设计组成框图3.流程图第二章详细设计1.功能说明系统通过简单的控制台界面,运行后在屏幕上显示功能菜单,列出该程序具有的功能,供用户选择,用户选择功能后应该转到相应的处理程序。
程序应该包括以下功能:(1)演示死锁现象;(2)通过资源按序分配法防止死锁;(3)通过资源预分配法防止死锁;(4)退出。
1.功能说明(1)演示死锁现象:演示死锁情况的哲学家线程函数,每个哲学家都得到了左边的筷子,又都在等待右边的筷子(2)通过资源按序分配法防止死锁:每个哲学家先申请左右两根筷子中编号小的筷子,再申请编号大的筷子。
操作系统实验报告哲学家就餐
操作系统实验报告哲学家就餐一、实验目的:通过模拟哲学家就餐问题,了解并掌握操作系统中的进程同步机制,以及解决进程间资源竞争所引发的死锁问题。
二、实验介绍:哲学家就餐问题是由荷兰计算机科学家伊克斯特拉(Dijkstra)于1965年首次提出的。
其问题描述如下:五位哲学家坐在一张圆桌子周围,每个哲学家面前有一碗饭和一根筷子。
哲学家的生活方式是交替地进行思考和进食。
当一个哲学家思考时,他不需要使用他的两个筷子;当一个哲学家想吃饭时,他需要同时获取他的左右两个筷子,并在获取到筷子后才能开始进食。
问题的关键是如何解决哲学家间的筷子竞争问题,以及避免死锁的发生。
三、实验设计:1.并发思路每个哲学家作为一个进程,在进行思考和进食这两个操作之前,需要获取他的两个筷子。
接下来考虑进程同步的两个关键点:-互斥:保证每个筷子同时只能被一个哲学家使用,避免资源竞争问题。
-死锁避免:通过限制只允许至多四位哲学家同时持有筷子,从而避免死锁发生。
2.进程同步机制- 互斥:使用Semaphore实现互斥,每个筷子都是一个Semaphore,初始值为1-死锁避免:引入一个全局计数器,记录当前持有筷子的哲学家数量,每次哲学家想要获取筷子时,先检查该计数器,仅当计数器小于4时才会获取筷子。
四、实验步骤:1.创建5个哲学家进程和5个筷子线程。
2.每个哲学家的线程循环执行思考和进食操作。
3.在进食之前,哲学家需要获取两个筷子,获取筷子的顺序按照哲学家编号进行,每个哲学家先获取自己的左边筷子,再获取自己的右边筷子。
4.进行进食操作后,哲学家释放两个筷子。
5.循环执行步骤3和步骤4,直到实验结束。
五、实验结果:通过观察实验结果,可以看到哲学家的思考和进食操作交替进行,并且避免了死锁的发生。
六、实验总结:通过本次实验,我了解了操作系统中的进程同步机制,并学会了如何解决资源竞争和死锁问题。
在本实验中,我使用了Semaphore和全局计数器实现了互斥和死锁避免,从而成功模拟了哲学家就餐问题。
操作系统哲学家就餐问题实验报告
#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<<"筷子的状态,用表示使用中,闲表示空闲中。
(完整word版)广东工业大学操作系统哲学家就餐问题
操作系统课程设计题目:哲学家就餐问题学院计算机学院专业软件工程班级12级3班学号3112006229 姓名陈志勇指导教师申建芳(2015年6月)操作系统课程设计任务书设计思想说明操作系统平台:Windows 2007开发平台:eclipse程序语言:Java设计思想:定义五个类,分别为哲学家A、哲学家B、哲学家C、哲学家D、哲学家E。
五个类均有thinking(思考)和Eating(吃饭)两个方法.当选定哪几位哲学家就餐后,使用单线程处理选定的哲学家就餐顺序,如果A要就餐,询问C是否要就餐,否则询问D 是否要就餐,否则A自己就餐;然后B进行就餐,如果B就餐,询问D是否要就餐,否则询问E是否要就餐,否则B就餐;然后C进行就餐,如果C就餐,询问E是否就餐,否则C 就餐;最后D就餐,再E就餐.数据结构的说明采用链式timer(计时器),每当一个timer结束时,链接到下一个timer中去,实现多步哲学家就餐顺序,当最后一个哲学家就餐完成后弹出信息面板提示就餐完成。
调用关系:ShowPannel为主类,StateControl为哲学家类,showPannel在timer中调用哲学家类实现就餐、思考的转换和选择。
各模块的算法流程图StateControl类:定义哲学家类Thinking:setText(空闲);Eating:setText(正在使用);showPannel类:点击确定后选定哲学家就餐A组:AC就餐AD就餐A就餐B组:BD就餐BE就餐B就餐C组:CE就餐C就餐D组:D就餐E组:E就餐Messagebox类:仅显示提示信息程序清单StateControl类:package philosopher;class philosopherA{void Thinking(){//正在思考时不占用筷子资源ShowPannel。
chops1。
setText("筷子1当前状态:空闲");ShowPannel.chops2。
华中科技大学操作系统实验报告
华中科技大学电信学院操作系统实验报告电子信息与通信学院班级:电信1202班姓名:XX学号:U*******XX时间:2014年11月5日实验一哲学家就餐问题一.实验目的1.熟悉哲学家就餐问题流程,编译程序,了解程序运行过程。
2.理解利用设置信号量及P、V操作解决进程间的互斥这一方法,并了解其代码实现的相关方法,提炼出代码的思想(用伪代码表示)。
3.对哲学家就餐问题提出新的解决方式,并简述其实现过程。
二.实验原理1、问题描述有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子。
每个哲学家的行为是思考,感到饥饿,然后吃通心粉。
为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。
2、分配方式方式一(不会进入死锁)仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子。
这样要么一次占有两只筷子(所有线程需要的资源)进行下一步的吃通心粉,然后释放所有的资源;要么不占用资源,这样就不可能产生死锁了。
方式二(会进入死锁)当筷子(资源)可用时,先分配左边的筷子,等待一会后再分配右边的筷子,由于这个过程中,左边的筷子一直没有释放,就有可能产生死锁了。
3、程序运行说明程序运行过程中会弹出一个MessageBox提示操作者操作:1)第一个对话框用于选择运行模式a.选择yes 表示采用的是运行的防止死锁的方式,这样的话整个程序可以一直运行下去,不会产生死锁。
b.选择no 表示运行产生死锁的方式会弹出第二个对话框。
2)第二个对话框用于选择运行时,线程运行的时间a. 选择res 线程时间比较短,很快就可以死锁b.选择no 线程时间跟选择yes 时候的时间差不多,产生死锁的时间稍微长一点。
三.实验程序流程及分析1、PhilosopherThread函数源代码DWORD WINAPI PhilosopherThread(LPVOID pVoid){HANDLE myChopsticks[2];int iPhilosopher = (int) pVoid;int iLeftChopstick = iPhilosopher;int iRightChopstick = iLeftChopstick + 1;DWORD result;if (iRightChopstick > PHILOSOPHERS-1) //筷子编号过了5就使它为0iRightChopstick = 0;//Randomize the random number generatorsrand( (unsigned)time( NULL ) * (iPhilosopher + 1) );// remember handles for my chopsticksmyChopsticks[0] = gchopStick[iLeftChopstick]; //定义哲学家的左右筷子myChopsticks[1] = gchopStick[iRightChopstick];gDinerState[iPhilosopher] = RESTING; //wants chopsticksSleep(P_DELAY);for(;;){if (bWaitMultiple == FALSE){// Wait until both of my chopsticks are availablegDinerState[iPhilosopher] = WAITING; //wants chopsticksPostMessage(hWndMain, WM_FORCE_REPAINT,0 ,0);result = WaitForSingleObject(gchopStick[iLeftChopstick], INFINITE);MTVERIFY(result == WAIT_OBJECT_0);gChopstickState[iLeftChopstick] = iPhilosopher;Sleep(P_DELAY/4);gDinerState[iPhilosopher] = WAITING; //wants chopsticksPostMessage(hWndMain, WM_FORCE_REPAINT,0 ,0);result = WaitForSingleObject(gchopStick[iRightChopstick], INFINITE);MTVERIFY(result == WAIT_OBJECT_0);gChopstickState[iRightChopstick] = iPhilosopher;}else{// Wait until both of my chopsticks are availablegDinerState[iPhilosopher] = WAITING; //wants chopsticksPostMessage(hWndMain, WM_FORCE_REPAINT,0 ,0);result = WaitForMultipleObjects(2, myChopsticks, TRUE, INFINITE);MTVERIFY(result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + 2);gChopstickState[iLeftChopstick] = iPhilosopher;gChopstickState[iRightChopstick] = iPhilosopher;}// Philosopher can now eat a grain of ricegDinerState[iPhilosopher] = EATING; //philosopher is eatingPostMessage(hWndMain, WM_FORCE_REPAINT,0 ,0);Sleep(P_DELAY);// Put down chopsticksgDinerState[iPhilosopher] = RESTING; //philosopher is restinggChopstickState[iRightChopstick] = UNUSED;gChopstickState[iLeftChopstick] = UNUSED;PostMessage(hWndMain, WM_FORCE_REPAINT,0 ,0);MTVERIFY( ReleaseMutex(gchopStick[iLeftChopstick]) ); //释放筷子资源MTVERIFY( ReleaseMutex(gchopStick[iRightChopstick]) );// Philosopher can now meditateSleep(P_DELAY);} // end forreturn 0;}2、伪代码对于每一个哲学家来说,他们需要抢占的临界资源就是左右的两支筷子。
操作系统实验报告哲学家就餐
线程同步操作系统实验报告实验目的:1.理解和掌握Linux线程控制的系统调用命令。
2.理解和掌握Linux线程同步的系统调用命令。
实验内容:1.Linux线程机制pthread 相关系统调用命令:pthread_create,pthread_join,pthread_mutex_lock,pthread_mutex_unlock,enter_region,leave_region等。
2. 多线程编程使用线程同步机制实现Dinning Philosophers算法。
实验代码:#include<unistd.h>#include<assert.h>#include<stdio.h>#include<stdlib.h>#include<pthread.h>#define phi_num 5#define think_time 2#define eat_time 1#define left (phi_id+phi_num-1)%phi_num#define right (phi_id+1)%phi_numenum { think , hungry , eat } phi_state[phi_num];pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t state[phi_num]={PTHREAD_MUTEX_INITIALIZER};void Do_think(int phi_id){printf(" philosopher %d is thinking now !\n",phi_id);sleep(think_time);}void Do_eat(int phi_id){printf("philosopher %d is eating now !\n",phi_id);sleep(eat_time);}void check_phi_state(int phi_id){if(phi_state[phi_id]==hungry&&phi_state[left]!=eat&&phi_state[right]!=e at){phi_state[phi_id]=eat;pthread_mutex_unlock(&state[phi_id]);}}void Do_take_forks(int phi_id){pthread_mutex_lock(&mutex);phi_state[phi_id]=hungry;check_phi_state(phi_id);pthread_mutex_unlock(&mutex);pthread_mutex_lock(&state[phi_id]);}void Do_put_forks(int phi_id){pthread_mutex_lock(&mutex);phi_state[phi_id]=think;check_phi_state(left);check_phi_state(right);pthread_mutex_unlock(&mutex);}void *philosopher(void *arg){int phi_id=*(int *)arg;while(1){Do_think(phi_id);Do_take_forks(phi_id);Do_eat(phi_id);Do_put_forks(phi_id);}return NULL;}int main(int argc, char *argv[]){int num;pthread_t *phi=(pthread_t*)malloc(sizeof(pthread_t)*phi_num);int *id=(int *)malloc(sizeof(int)*phi_num);for(num=0;num<phi_num;num++){id[num]=num;pthread_create(&phi[num],NULL,philosopher,(void*)(&id[num]));}for(num=0;num<phi_num;num++){pthread_join(phi[num],NULL);}return 0;}截图:。
哲学家就餐问题报告
哲学家就餐问题报告一、实验目的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.简介1.1 背景介绍哲学家进餐问题是计算机科学中一个经典的并发问题,最早由Edsger Dijkstra在1965年提出。
1.2 问题描述问题的场景是五位哲学家围坐在一张圆桌前,每个哲学家面前有一碗饭和一根筷子。
哲学家需要交替地思考和进餐,但是他们只能使用左右两边的筷子来进餐。
1.3 目标设计一个算法来保证哲学家们能够交替地进餐,同时避免死锁和饥饿现象的发生。
2.解决方案2.1 简单解法一个简单的解法是给每个哲学家编号,规定奇数号哲学家先拿左边的筷子,偶数号哲学家先拿右边的筷子。
当一个哲学家需要拿筷子时,他会先检查他的两边是否有其他哲学家正在使用,如果没有,他就可以拿起两边的筷子进餐。
否则,他需要等待直到两边的筷子都可用。
2.2 改进解法上述简单解法可能会导致死锁问题。
为了避免死锁,我们可以引入资源分级的概念。
每个筷子被分为两个等级,分别是主要资源和次要资源。
哲学家需要按照顺序来获取资源,例如,先获取主要资源,然后获取次要资源。
3.算法实现3.1 数据结构我们可以使用一个数组来表示圆桌上的五个筷子,同时使用一个锁数组来表示每个筷子的状态(是否被占用)。
3.2 算法流程在哲学家进餐问题中,每个哲学家都需要经历思考和进餐两个过程,我们可以使用线程来模拟这两个过程。
4.算法分析4.1 死锁问题通过引入资源分级的概念,我们成功避免了死锁问题的发生。
每个哲学家按照顺序获取资源,不会出现他们都在等待同一个资源的情况。
4.2 饥饿问题在我们的算法中,每个哲学家都会交替地进餐和思考,因此不会出现饥饿问题。
5.附件本文档暂无附件。
6.法律名词及注释6.1 死锁死锁是指在并发系统中,两个或多个进程或线程无限期地互相等待对方所占有的资源的情形。
6.2 饥饿饥饿是指某个进程或线程因无法获得所需的资源而无法继续执行的情况。
操作系统哲学家就餐问题实验报告
操作系统哲学家就餐问题实验报告实验目的:通过实验探究操作系统中的哲学家就餐问题,了解并掌握解决该问题的不同算法。
实验原理:哲学家就餐问题是一个典型的并发控制问题,该问题描述了一群哲学家围坐在圆桌上,每个哲学家左右两边各有一只筷子,哲学家只有同时拿到左右两只筷子时才能进餐,进餐完毕后将筷子放回桌面。
该问题的解决涉及到互斥、死锁、饥饿等并发问题。
实验步骤: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)。
线程同步
操作系统实验报告
实验目的:
1.理解和掌握Linux线程控制的系统调用命令。
2.理解和掌握Linux线程同步的系统调用命令。
实验内容:
1.Linux线程机制pthread 相关系统调用命令:
pthread_create,pthread_join,pthread_mutex_lock,
pthread_mutex_unlock,enter_region,leave_region等。
2. 多线程编程使用线程同步机制实现Dinning Philosophers算法。
实验代码:
#include<>
#include<>
#include<>
#include<>
#include<>
#define phi_num 5
#define think_time 2
#define eat_time 1
#define left (phi_id+phi_num-1)%phi_num
#define right (phi_id+1)%phi_num
enum { think , hungry , eat } phi_state[phi_num];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t state[phi_num]={PTHREAD_MUTEX_INITIALIZER};
void Do_think(int phi_id){
printf(" philosopher %d is thinking now !\n",phi_id);
sleep(think_time);
}
void Do_eat(int phi_id){
printf("philosopher %d is eating now !\n",phi_id);
sleep(eat_time);
}
void check_phi_state(int phi_id){
if(phi_state[phi_id]==hungry&&phi_state[left]!=eat&&phi_state[right]!=e at){
phi_state[phi_id]=eat;
pthread_mutex_unlock(&state[phi_id]);
}
}
void Do_take_forks(int phi_id){
pthread_mutex_lock(&mutex);
phi_state[phi_id]=hungry;
check_phi_state(phi_id);
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&state[phi_id]);
}
void Do_put_forks(int phi_id){
pthread_mutex_lock(&mutex);
phi_state[phi_id]=think;
check_phi_state(left);
check_phi_state(right);
pthread_mutex_unlock(&mutex);
}
void *philosopher(void *arg){
int phi_id=*(int *)arg;
while(1){
Do_think(phi_id);
Do_take_forks(phi_id);
Do_eat(phi_id);
Do_put_forks(phi_id);
}
return NULL;
}
int main(int argc, char *argv[]){
int num;
pthread_t *phi=(pthread_t*)malloc(sizeof(pthread_t)*phi_num);
int *id=(int *)malloc(sizeof(int)*phi_num);
for(num=0;num<phi_num;num++){
id[num]=num;
pthread_create(&phi[num],NULL,philosopher,(void*)(&id[num]));
}
for(num=0;num<phi_num;num++){
pthread_join(phi[num],NULL);
}
return 0;
}
截图:。