操作系统哲学家就餐问题实验报告
实验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]); 顺序改变下,运行结果有变化?
操作系统课程设计——哲学家进餐问题
操作系统课程设计——哲学家进餐问题1000字哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着广泛的应用。
因此,在操作系统课程设计中,探究哲学家进餐问题是一件非常有意义的事情。
哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。
每个哲学家有两种状态:思考和进餐。
当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这两只筷子,进入思考状态。
在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法拿到右手边的筷子,导致无法进餐。
因此,需要在代码中实现同步互斥机制,避免死锁的发生。
本课程设计中,我使用了Java语言来实现哲学家进餐问题。
在代码实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来模拟哲学家的思考和进餐过程。
为了避免死锁,我使用了Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。
同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等待下一个机会。
在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。
每个筷子都是一个二元信号量,初始为1,表示可用。
当一个哲学家拿起筷子时,他会将对应的信号量减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);} else {acquire(right_fork_id);acquire(left_fork_id);}}release_forks(left_fork_id, right_fork_id) { release(left_fork_id);release(right_fork_id);}philosopher(id) {while (true) {think();acquire_forks(id, (id + 1) % 5);eat();release_forks(id, (id + 1) % 5);}}```4. 附件本文档不涉及附件。
哲学家吃饭问题试验报告操作系统
目录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附件:。
实验一 哲学家就餐问题
实验一哲学家就餐问题一、实验目的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-哲学家就餐问题
实验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、程序当中产生异常的点很多,在一个大的应用程序当中(有众多的类),无论哪种异常发生后,如何集中在一处统一给出中文提示。
(完整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。
哲学家就餐问题
哲学家就餐问题实验⼀⼀、实验名称:哲学家就餐问题的实现⼆、实验学时: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. 程序代码(重要代码请注释)#include#include#include#include#include#define NOC 5 //number of chopstic#define NOP 5 //number of philosopher sem_t chopstic[NOC]; //semaphoreint flag[5]; //philosopher's statusvoid *eat(int i){int position;int temp = 0;int j = (i+1)%NOC;position = i%2;while(1){if(position == 0){ //odd take left first sem_wait(&chopstic[i]);sem_wait(&chopstic[j]);printf("philosopher%d get %d\n", i, j);flag[i] = 1; //philosopher is eatingprintf("waitting:"); //print others' statuswhile(temp < 5){if(!flag[temp])printf("philosopher%d\t", temp);temp++;}temp = 0;printf("\n");printf("eating:");// print others' statuswhile(temp < 5){if(flag[temp])printf("philosopher%d\t", temp);temp++;}printf("\n\n");temp = 0;//printf("\nphilosopher%d is eating\n\n", i); sleep(2);flag[i] = 0;printf("philosopher%d put %d\n", i, i); sem_post(&chopstic[i]); printf("philosopher%d put %d\n", i, j); sem_post(&chopstic[j]); }else{ //even take right firstsem_wait(&chopstic[j]);printf("philosopher%d get %d\n", i, j);sem_wait(&chopstic[i]);printf("philosopher%d get %d\n", i, i);flag[i] = 1;printf("waitting:");while(temp < 5){if(!flag[temp])printf("philosopher%d\t", temp);}temp = 0;printf("\n");printf("eating:");while(temp < 5){if(flag[temp])printf("philosopher%d\t", temp);temp++;printf("\n\n");temp = 0;//printf("\nphilosopher%d is eating\n\n", i);sleep(2);flag[i] = 0;printf("philosopher%d put %d\n", i, j);sem_post(&chopstic[j]);printf("philosopher%d put %d\n", i, i);sem_post(&chopstic[i]);}}}int main(void){int i = 0;int error;pthread_t philosopher[NOP];//init semwhile(i < 5){flag[i] = 0;sem_init(&chopstic[i], 0, 1);i++;}i = 0;//create threadwhile(i < 5){error = pthread_create(&philosopher[i], NULL, (void *)eat, (void *)i);printf("error:create thread failed!!\n");exit(0);}i++;}//destroy threadwhile(i < 5){pthread_join(philosopher[i], NULL);i++;}i = 0;//destroy semwhile(i < 5){sem_destroy(&chopstic[i]);i++;}return 0;}七、实验及结果分析:运⾏结果:udbwxfso@ubuntu:~/Desktop/sy2$ gcc gphilosopher.c -pthread udbwxfso@ubuntu:~/Desktop/sy2$ ./a.out philosopher4 get 4philosopher4 get 0waitting:philosopher0 philosopher1 philosopher2 philosopher3 eating:philosopher4philosopher2 get 2philosopher2 get 3waitting:philosopher0 philosopher1 philosopher3eating:philosopher2 philosopher4philosopher4 put 4philosopher4 put 0philosopher4 get 4philosopher4 get 0waitting:philosopher0 philosopher1 philosopher3eating:philosopher2 philosopher4philosopher2 put 3philosopher2 get 2philosopher2 get 3waitting:philosopher0 philosopher1 philosopher3eating:philosopher2 philosopher4philosopher4 put 4philosopher3 get 4philosopher4 put 0philosopher0 get 0philosopher0 get 1waitting:philosopher1 philosopher3 philosopher4eating:philosopher0 philosopher2philosopher2 put 2philosopher2 put 3philosopher2 get 2philosopher2 get 3waitting:philosopher1 philosopher3 philosopher4eating:philosopher0 philosopher2philosopher2 put 2philosopher2 put 3philosopher2 get 2philosopher2 get 3waitting:philosopher1 philosopher3 philosopher4eating:philosopher0 philosopher2经分析可知,放在桌⼦上的筷⼦是临界资源,在⼀段时间内只允许⼀位哲学家使⽤,为了实现对筷⼦的互斥使⽤,⽤⼀个信号量表⽰⼀只筷⼦,由这五个信号量组成信号量数组。
实践 15 哲学家进餐问题
实践15 哲学家进餐问题1.实践内容说明(1)在函数中使用图形方式显示哲学家进餐问题,每个哲学家使用一个线程控制,随机进行进餐或者思考,使用互斥量和事件进行同步和互斥控制。
2.程序性质(1)Windows 和控制台混合应用程序(2)多线程3.运行环境设置(1)建立项目在Visual C++ 6.0 开发环境,单击New 菜单,弹出New 对话框;在New 对话框中选择Project 标签切换至Project 标签页;在Project 标签页的项目列表中选择Win32 Application 选项,Location 输入框输入项目所在的路径,或者单击输入框右侧的按钮,在弹出的Choose Directory 对话框中选择项目所在的磁盘分区和所在的目录;在Project 标签页的Project name 输入框中输入项目名称;Project 标签页中的其他选项保持默认选择(单选框Create new workspace 前有黑点,Platforms 选项框中Win32 前打勾),完成设置界面如图10 所示。
图10 设置项目为Windows 应用完成设置后单击OK,New 对话框关闭,弹出Win32 Console Application –Step 1 of 1 对话框。
在Win32 Console Application –Step 1 of 1 对话框中选择An empty project 单选项。
Win32 Console Application –Step 1 of 1 对话框如图11 所示。
图11 说明刚建立的项目为空项目完成Win32 Console Application –Step 1 of 1 对话框后单击Finish 按钮,Win32 Console Application –Step 1 of 1 对话框关闭,弹出New Project Information 对话框。
New Project Information 对话框中显示了当前建立项目的一些信息。
哲学家吃饭问题 实验报告 操作系统
欢迎共阅目录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 为了避免死锁,把哲学家分为三种状态,思考,饥饿,进食,仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子,并且一次拿到两只筷子,否则不拿。
操作系统哲学家问题
《操作系统》实验报告实验序号:03实验项目名称:哲学家问题学号姓名专业、班信管1303实验地点文波楼217实验室指导教师时间2014年11月29日一、实验目的及要求一个房间里有5个哲学家,他们的生活是思考和吃饭,房间里有一张圆桌,中间放着一碗饭菜(假设饭菜无限多),桌子周围放有5把椅子,分别属于5位哲学家,每两位哲学家之间有一把勺子,哲学家进食时必须同时使用左右两把勺子,请为每位哲学家设计一个程序,解决他们的吃饭问题。
二、实验设备(环境)及要求硬件:一台计算机软件:装有Linux操作系统,终端窗口,文本编辑器。
三、实验内容与步骤实验代码:#include<stdio.h>#include<stdlib.h>#include<time.h>#include<semaphore.h>#include<sys/mman.h>#define F1 PROT_READ|PROT_WRITE#define F2 MAP_SHARED|MAP_ANONYMOUS#define N 5 //人数#define L 3 //行为循环次数typedef struct{sem_t ph[N];sem_t mutex;int state[N];int t;}pair;pair * p;void think(int i){printf("%d号哲学家在思考....\n", i);srand((unsigned)time(NULL));int n=rand()%10;usleep(1000000*n);printf("%d号哲学家思考完成!\n", i);}void eat(int i){printf("%d号哲学家在吃饭\n", i);srand((unsigned)time(NULL));int n=rand()%4;usleep(4000000+n*1000000);printf("%d号哲学家吃饭结束!\n\n", i);}void test(int i){if((p->state[i]==2) && (p->state[(i+1)%N]!=3) && (p->state[(N+i-1)%N]!=3)) {p->state[i]=3;sem_post(&(p->ph[i]));}}void philosopher(int i){int l=L;while(l--){think(i);sem_wait(&(p->mutex));p->state[i]=2;test(i);sem_post(&(p->mutex));sem_wait(&(p->ph[i]));eat(i);sem_wait(&(p->mutex));p->state[i]=1;test((N+i-1)%N);test((i+1)%N);sem_post(&(p->mutex));}p->t++;//t==0时父进程也要结束exit(0);}void main(){p=(pair*)mmap(NULL, sizeof(pair), F1, F2, -1, 0);//为变量开辟共享内存int i, pid;for(i=0;i<N;i++){p->state[i]=1;sem_init(&(p->ph[i]), 1, 0);}sem_init(&(p->mutex), 1, 1);p->t=0-N;for(i=0;i<N;i++){pid=fork();if(pid==0)philosopher(i);}if(pid>0){while(1)if((p->t)<0){printf("....\n");usleep(5000000);}else{//子进程已经结束,for(i=0;i<N;i++)sem_destroy(&(p->ph[i]));sem_destroy(&(p->mutex));printf("程序结束!\n");exit(0);}}}运行时也要注意线程,要输入lpthread四、实验结果与数据处理运行界面:五、分析与讨论这个问题看起来难以实现,虽然老师上课讲过,但开始拿到也觉得没那么容易,思想解决了,代码还要一步步运行,这个程序对P,V操作的用法很深,一不小心就会弄错,但是写完了之后也发现并不是想象中的那么难。
操作系统实验报告哲学家就餐
线程同步操作系统实验报告实验目的: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;}截图:。
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<<"筷子状态, 用表示使用中, 闲表示空闲中。
哲学家就餐问题报告
哲学家就餐问题报告一、实验目的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.最后画哲学家的手:判断的依据是若筷子的编号和哲学家的编号一直致,那么认为这根筷子属于这个哲学家(筷子资源空闲)那么可以画手表示哲学家获得了这个筷子。
操作系统哲学家进餐实验
《操作系统》实验报告实验题目:哲学家进餐问题一、实验目的:实现linux下哲学家进餐问题。
体会如何控制进程同步与互斥的信号量方法。
二、实验内容:运用linux下fork,IPC信号量机制中的相关系统调用,IPC共享存储器机制,实现哲学家进餐问题。
三、编程环境及工具Linux下GCC四、具体设计要求及有关说明Fork() 在子进程刚被创建时,它和父进程具有相同的共享正文段,而其他进程信息则完全拷贝父进程得到。
信号量调用的示例程序:#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <stdio.h>union semun {int val;struct semid_ds *buf;ushort * array;}argument;int main(){int id; /* Number by which the semaphore is known within a program */argument.val = 0;//新建一个信号量集合,包含一个信号量id = semget(IPC_PRIV ATE, 1, 0666 | IPC_CREAT);if(id < 0){printf("Unable to obtain semaphore.\n ");exit(-1);}//将信号量的值置为0if( semctl(id, 0, SETV AL, argument) < 0){printf("Cannot set semaphore value.\n");}else{printf("Semaphore initialized.\n");}}int lock_sem(int semid, int member){/*初始化sembuf结构,将指定信号量值减1。
哲学家进餐问题(操作系统)
哲学家进餐问题(操作系统)哲学家进餐问题(操作系统)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. 分析实验结果,比较两种算法的优缺点。
实验结果与分析:通过观察实验程序运行的结果,可以发现在基于信号量的解法中,哲学家的就餐过程是以并发的方式进行的,每个哲学家在不产生死锁的前提下获取到筷子并进餐。
但是,由于每个哲学家只能同时拿到一只筷子,有可能会出现饥饿的情况,即某个哲学家一直无法获取到筷子进餐。
而基于管程的解法则能够避免饥饿的问题,每个哲学家在进餐前都会检查是否有足够的筷子可用,若不可用则等待。
通过互斥锁的使用,确保每次只有一个哲学家能够进入管程进行操作,避免了并发产生的问题。
综上所述,基于管程的解法相对于基于信号量的解法更加可靠,能够避免饥饿问题的出现。
但是在实际应用中,两种解法的选择还需要根据具体情况进行权衡和取舍。
操作系统哲学家就餐问题实验报告
操作系统哲学家就餐问题实验报告图5.测试结果1#include#include#include#include#includeusing 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<<"-----------------------状态说明⽰意图:-----------------------"<cout<<" "<<"哲学家1号的状态"<<" "<cout<<" 筷⼦0的状态"<<" "<<"筷⼦1的状态"<cout<<"哲学家5号的状态"<<" "<<"哲学家2号的状态"<cout<<" 筷⼦4的状态"<<" "<<"筷⼦2的状态"<cout<<" 哲学家4号的状态"<<" "<<"哲学家3号的状态"<cout<<" "<<"筷⼦3的状态"<//cout<<" "<<"哲学家3号的状态"<<" "<cout<<"筷⼦的状态,⽤表⽰使⽤中,闲表⽰空闲中。
操作系统哲学家问题实验报告
实验报告三实验名称:一、调试验证“有限缓冲”经典同步问题二、利用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)问题分析当出现以下情形,在某一瞬间,所有的哲学家都同时启用这个算法,拿起左侧的筷子,而看到右侧筷子都不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此永远重复下去。
对于这种情况,所有的程序都在运行,但却都无法取得进展,即出现饿死,所有的哲学家都吃不上饭。
解决死锁问题:为了避免死锁,把哲学家分为三种状态:思考,饥饿(等待),进食,并且一次拿起两只筷子,否则不拿。
实践 15 哲学家进餐问题
实践15 哲学家进餐问题1.实践内容说明(1)在函数中使用图形方式显示哲学家进餐问题,每个哲学家使用一个线程控制,随机进行进餐或者思考,使用互斥量和事件进行同步和互斥控制。
2.程序性质(1)Windows 和控制台混合应用程序(2)多线程3.运行环境设置(1)建立项目在Visual C++ 开发环境,单击New 菜单,弹出New 对话框;在New 对话框中选择Project 标签切换至Project 标签页;在Project 标签页的项目列表中选择Win32 Application 选项,Location 输入框输入项目所在的路径,或者单击输入框右侧的按钮,在弹出的Choose Directory 对话框中选择项目所在的磁盘分区和所在的目录;在Project 标签页的Project name 输入框中输入项目名称;Project 标签页中的其他选项保持默认选择(单选框Create new workspace 前有黑点,Platforms 选项框中Win32 前打勾),完成设置界面如图10 所示。
图10 设置项目为Windows 应用$完成设置后单击OK,New 对话框关闭,弹出Win32 Console Application –Step 1 of 1 对话框。
在Win32 Console Application –Step 1 of 1 对话框中选择An empty project 单选项。
Win32 Console Application –Step 1 of 1 对话框如图11 所示。
图11 说明刚建立的项目为空项目完成Win32 Console Application –Step 1 of 1 对话框后单击Finish 按钮,Win32 Console Application –Step 1 of 1 对话框关闭,弹出New Project Information 对话框。
New Project Information 对话框中显示了当前建立项目的一些信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统哲学家就餐问题实验报告Company number:【0089WT-8898YT-W8CCB-BUUT-202108】附录:源代码#include <>#include <>#include <string>#include <iostream>#include <>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<<"筷子的状态,用表示使用中,闲表示空闲中。
"<<endl;cout<<"--------------------------------------------------------------"<<endl;//cout<<"哲学家们开始生活:"<<endl;//cout<<"当前状态:";cout<<endl;//cin>>con;while(con=='y'){(); (); (); (); ();cout<<"当前状态为:"<<endl;cout<<" "<<()<<print(&P1)<<" "<<endl;cout<<" "<<toolstatus(tools[0])<<""<<toolstatus(tools[1])<<endl;cout<<" "<<()<<print(&P5)<<" "<<()<<print(&P2)<<endl;cout<<" "<<toolstatus(tools[4])<<""<<toolstatus(tools[2])<<endl;cout<<" "<<()<<print(&P4)<<" "<<()<<print(&P3)<<endl;cout<<" "<<toolstatus(tools[3])<<endl;cout<<"--------------------------"<<endl;cout<<"若要继续下一状态,输入y;输入n进入死锁;输入其他,结束程序:";cin>>con;Sleep(20);}while(con=='n'){();(); (); (); ();cout<<"死锁情况"<<endl;cout<<" "<<()<<print(&P1)<<" "<<endl;cout<<" "<<toolstatus(tools[0])<<""<<toolstatus(tools[1])<<endl;cout<<" "<<()<<print(&P5)<<" "<<()<<print(&P2)<<endl;cout<<" "<<toolstatus(tools[4])<<""<<toolstatus(tools[2])<<endl;cout<<" "<<()<<print(&P4)<<" "<<()<<print(&P3)<<endl;cout<<" "<<toolstatus(tools[3])<<endl;cout<<"--------------------------"<<endl; cout<<"输入n继续;输入其他,结束程序:";cin>>con;Sleep(20);}DeleteCriticalSection (&cs) ; //退出资源区return 0;}。