实践 哲学家进餐问题
哲学家进餐问题

哲学家进餐问题问题描述:有5个哲学家共用一张圆桌,分别坐在周围的5张椅子上。
在桌上有5支筷子和5个碗,他们的生活方式是交替的进行思考和进餐。
平时,一个哲学家进行思考,饥饿时便试图取用他左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。
进餐完毕放下筷子继续思考。
解决方法:1)至多只允许4位哲学家同时去拿他左边的筷子,最终能保证至少有一个哲学家能够进餐,并在用毕时能够释放他用过的两支筷子,从而使更多的哲学家能够进餐。
2)规定奇数号哲学家先拿他左边的筷子然后再拿右边的筷子;而偶数号哲学家则与此相反。
3)仅当哲学家的左右两边的筷子都能用时才允许他拿起筷子进餐。
用第3)种方法解决代码如下:#include <stdio.h>#include <stdlib.h>#include <windows.h>#include <time.h>#define PHILOSOPHERS 5HANDLE gchopStick[PHILOSOPHERS];DWORD WINAPI PhilosopherThread(LPVOID pVoid) {HANDLE myChopsticks[2];DWORD result;int iPhilosopher = (int) pVoid;int iLeftChopstick = iPhilosopher;int iRightChopstick = iLeftChopstick + 1;if (iRightChopstick > PHILOSOPHERS-1)iRightChopstick = 0;myChopsticks[0] = gchopStick[iLeftChopstick];myChopsticks[1] = gchopStick[iRightChopstick];result=WaitForMultipleObjects(2,myChopsticks,TR UE,-1);printf("the %d PHILOSOPHER begin to eat\n",iPhilosopher);Sleep(200);printf("the %d PHILOSOPHER finishedeating",iPhilosopher);ReleaseMutex(myChopsticks[0]);ReleaseMutex(myChopsticks[1]);return EXIT_SUCCESS;}int main(int argc,char *argv[]){DWORD dwThreadId,wait_for_all;HANDLE hThread[PHILOSOPHERS];for (int i=0; i < PHILOSOPHERS; i++){gchopStick[i] = CreateMutex(NULL, FALSE, NULL);}for (i = 0; i < PHILOSOPHERS; i++)hThread[i] = CreateThread(NULL, 0, PhilosopherThread, (LPVOID) i, 0, &dwThreadId);wait_for_all=WaitForMultipleObjects(PHILOSOPHER S,hThread,TRUE,-1);printf("All PHILOSOPHERs finished eating\n");return 0; }。
操作系统课程设计——哲学家进餐问题

操作系统课程设计——哲学家进餐问题1000字哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着广泛的应用。
因此,在操作系统课程设计中,探究哲学家进餐问题是一件非常有意义的事情。
哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。
每个哲学家有两种状态:思考和进餐。
当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这两只筷子,进入思考状态。
在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法拿到右手边的筷子,导致无法进餐。
因此,需要在代码中实现同步互斥机制,避免死锁的发生。
本课程设计中,我使用了Java语言来实现哲学家进餐问题。
在代码实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来模拟哲学家的思考和进餐过程。
为了避免死锁,我使用了Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。
同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等待下一个机会。
在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。
每个筷子都是一个二元信号量,初始为1,表示可用。
当一个哲学家拿起筷子时,他会将对应的信号量减1,表示不可用。
当哲学家用完筷子之后,会将对应的信号量加1,表示可用。
通过这种方式,实现了对筷子的访问同步。
最后,我对代码进行了测试,模拟了多位哲学家同时进行进餐的过程。
在测试中,我发现哲学家进餐的速度受到筷子的数量和哲学家思考进餐比例的影响。
当筷子数量少于哲学家数量时,容易出现死锁;当哲学家思考和进餐的时间相当时,程序的运行情况比较稳定。
总的来说,本课程设计实现了哲学家进餐问题,通过学习该问题,我更深入地理解了同步互斥机制的重要性,并学会了如何使用信号量来实现同步互斥。
五个哲学家吃饭问题详细解答

五个哲学家吃饭问题详细解答在一个阳光明媚的下午,五个哲学家聚在一起,准备享用一顿丰盛的午餐。
听起来很简单吧?但实际上,这顿饭可没那么容易!让我们来看看这群头脑发达的哲学家是如何在吃饭问题上纠结的。
1. 场景设定1.1 哲学家的基本设定这五位哲学家,一个比一个聪明。
他们分别是苏格拉底、柏拉图、康德、尼采和海德格尔。
你可以想象,他们脑袋里装的全是复杂的哲学思想,而不是食物的搭配。
所以,当这五位坐下来,面对一桌子美味的食物时,事情就开始变得有趣了。
1.2 吃饭的挑战问题来了:他们每个人都必须遵守一个规则——不可以同时吃饭,得轮流。
你想想,五个哲学家加上一个轮流吃饭的规则,这可真是“见鬼了”的挑战!想要吃上一口美味的菜,简直比推理一个哲学命题还难。
他们轮流吃饭的原则,真是把这顿饭变成了一场智力的较量。
2. 各自的哲学观2.1 苏格拉底的理性苏格拉底首先站出来,他一边抚摸着自己的胡须,一边说:“吃饭嘛,首先得用理性来解决问题。
”他鼓励大家先讨论,谁应该先吃,谁应该后吃。
他认为,只有通过理性对话,才能达到最佳的吃饭方案。
可是,你能想象吗?这一讨论持续了整整一个小时,食物都快冷掉了!2.2 柏拉图的理想接着柏拉图出场,他满脸严肃地说:“我们要追求理想的吃饭方式。
”他想出了一个绝妙的主意:每个人都应该依照自己的德性来决定吃的顺序。
结果,大家一顿争论,谁的德性更高?苏格拉底说他是智者,康德坚持说自己是道德之父,而尼采则跳出来,吼着“超人才能吃超好的饭!”搞得大家乱成一团,吃的机会又飞了。
3. 饥饿的对抗3.1 食物的诱惑这时,桌子上的食物开始散发出诱人的香气,真是令人垂涎欲滴。
五位哲学家每个人的肚子都开始抗议,仿佛在唱着“我们要吃饭”的歌。
吃饭这件事,从理性讨论变成了一场生存竞争。
每个人都在默默地想着:“快点!要是再不吃,我的哲学思想就要被饿死了!”3.2 轮流的尴尬最终,他们决定采取轮流吃饭的方式。
可当轮到康德的时候,他又开始喋喋不休,讲起了“绝对命令”的哲学,让其他人都想打瞌睡。
哲学家进餐问题

哲学家进餐问题1.问题描述:哲学家进餐问题描述有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。
约束条件(1)只有拿到两只筷子时,哲学家才能吃饭。
(2)如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。
(3)任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子。
2.求解方法(1).信号量的设置放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥访问,可以用一个信号量表示筷子,由这五个信号量构成信号量数组。
semaphore chopstick[5] = {1,1,1,1,1};while(true){/*当哲学家饥饿时,总是先拿左边的筷子,再拿右边的筷子*/wait(chopstick[i]);wait(chopstick[(i+1)%5]);// 吃饭/*当哲学家进餐完成后,总是先放下左边的筷子,再放下右边的筷子*/signal(chopstick[i]);signal(chopstick[(i+1)%5]);}上述的代码可以保证不会有两个相邻的哲学家同时进餐,但却可能引起死锁的情况。
假如五位哲学家同时饥饿而都拿起的左边的筷子,就会使五个信号量chopstick都为0,当他们试图去拿右手边的筷子时,都将无筷子而陷入无限期的等待。
(2)避免死锁策略一原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。
定义信号量count,只允许4个哲学家同时进餐,这样就能保证至少有一个哲学家可以就餐。
semaphore chopstick[5]={1,1,1,1,1};semaphore count=4; // 设置一个count,最多有四个哲学家可以进来void philosopher(int i){while(true){think();wait(count); //请求进入房间进餐 当count为0时 不能允许哲学家再进来了wait(chopstick[i]); //请求左手边的筷子wait(chopstick[(i+1)%5]); //请求右手边的筷子eat();signal(chopstick[i]); //释放左手边的筷子signal(chopstick[(i+1)%5]); //释放右手边的筷子signal(count); //退出房间释放信号量}}策略二原理:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。
哲学家用餐问题

哲学家一(线程一函数)
读懂整 个程序。 请写出其余两个线程 的函数Thread2Proc 和 Thread3Proc ,使他们 都先取右边的筷子, 后取左边的筷子。执 行,写出实验结果或 现象。回答问题(3)
(2)描述一个既没有两座同时吃饭,又没有人饿死(永远拿 到到筷子)的算法。
• 对上面的程序Байду номын сангаас行改进,完成题目(2)要求。
选做题:
• 根据以前做过的实验,把算法移植到给定的图形用户界 面(GUI)框架程序中,每个线程创建自己的窗口,每个哲 学家的吃饭和取筷子信息显示在自己的窗口界面中,每 个窗口中右键单击时开始取筷子和吃饭的过程。 • 为降低图形化开发的难度,可以只设计三个哲学家线程, 每个线程设计自己的线程函数(即不合并线程函数)。 • 执行时以各种顺序在三个窗口中右击,验证执行结果。
• 思考:改变放下左右两边的筷子的顺序会有影 响吗?验证执行。
程序改进二: 把三个线程函数合并成一个统一的线程函数,哲学家的编号由 线程的函数参数传入,根据前面的程序代码完成省咯号处的设 计,并完成主函数的相应修改。执行,记录结果。
DWORD WINAPI ThreadProc( LPVOID lpParameter ) { int index; index=*(int *)lpParameter; …… return 0; } int main() { int num=1; h_Thread[0]=CreateThread(NULL,0 ,ThreadProc,&num ,0,NULL); num++; h_Thread[1]=CreateThread(NULL,0 ,ThreadProc,&num ,0,NULL); num++; h_Thread[2]=CreateThread(NULL,0 ,ThreadProc,&num ,0,NULL); }
例:经典的IPC问题--哲学家进餐问题 问题描述: 五个哲学家围坐在

时间再试。问题是:如果大家同时拿起来左边,再同时放下,过一会再同时拿起来左边的
解法2: 设置一个信号量:mutex,初值为1,每个哲学家要想拿左边的叉子前,先P(mutex),如果成功拿到左边的叉子,则只有他自己在临界区中,必然可以顺利拿到右边的叉子.使用完后应该V(mutex).这样做的确避免了冲突,但同时只能有一个哲学家在吃饭.而五把叉子可供二名哲学家同时进餐.如果把mutex初值改为2,问题是:相邻两个哲学家仍然会冲突.现在请你设计一个算法,使得冲突可以避免,而且效率最高.
{
while (TRUE)//无限循环
{
think();//哲学家正在思考
take_forks(i);//需要两只叉子,或者阻塞
eat();//进餐
put_forks(i);//把两把叉子同时放回桌上
}
}
void take_forks(int i)//哲学家号码,从0到N-1
{
P(&mutex);//进入临界区
test(LEFT);//看一下左邻居现在是否能进餐
test(RIGHT);//看一下右邻居现在是否能进餐
V(&mutex);//离开临界区
}
void test(int i)//哲学家号码,从0到N-1
{
if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING)
take_fork(); //取左边的叉子
take_fork((i+1)%N); //取右边的叉子,%为取余
实验四模拟“五个哲学家”问题

实验四模拟"五个哲学家"问题魏陈强学号: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、问题描述⼀张圆桌上有5名哲学家,没两个哲学家之间有⼀根筷⼦,桌⼦中间由⼀碗⽶饭。
当哲学家饥饿时会试图分别拿起左右两根筷⼦,如果筷⼦已在他⼈⼿上则需等待。
饥饿的哲学家只有拿起两根筷⼦才能进餐,吃完后才能放下筷⼦。
2、问题分析对哲学家分别编号0,1,2,3,4,对筷⼦编号0,1,2,3,4。
i号哲学家左边筷⼦编号为i,右边编号为(i+1)%5。
(1)⽅案1最多允许4个哲学家同时申请进餐,这样可以保证⾄少有⼀个哲学家有两根筷⼦(2)⽅案2要求奇数号的哲学家先拿左边的筷⼦,然后拿右边的筷⼦,偶数号哲学家相反semaphore chopstick[5]={1,1,1,1,1};Pi(){while(1){if(i%2!=0){P(chopstick[i]);P(chopstick[(i+1)%5]);}else{P(chopstick[(i+1)%5]);P(chopstick[i]);}进餐V(chopstick[i]);V(chopstick[(i+1)%5]);}}(3)⽅案3仅当哲学家两边的筷⼦都可以拿起的时候才能申请进餐semaphore chopstick[5]={1,1,1,1,1};semaphore mutex=1;Pi(){while(1){P(mutex);P(chopstick[i]);P(chopstick[(i+1)%5]);V(mutex);吃饭V(chopstick[i]);V(chopstick[(i+1)%5]);}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
完成New对话框设置后,单击OK按钮关闭New对话框,在项目中创建文件步骤完成。(3)输入文件在创建得文件窗口中输入要调试运行得操作系统源文件。
(4)修改编译设置单击Project菜单中得Settings菜单项,弹出Project Settings对话框。在Project Settings对话框中单击C/C++标签,切换至C/C++标签页;在C/C++标签页中得Category下拉列表选择框中选择Code Generation选择项;在Use run-time library下拉列表选择框中选择Debug Multithreaded DLL选项。设置界面如图14所示。
图11说明刚建立得项目为空项目
完成Win32 Console Application–Step 1 of 1对话框后单击Finish按钮,Win32 Console Application–Step 1 of 1对话框关闭,弹出New Project Information对话框。New Project Information对话框中显示了当前建立项目得一些信息。New Project Information对话框如图12所示。
实践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所示。
int chopXY[8];//
int Id; //哲学家得编号
int isEating;
}PARAM;
#define PHIL_NUM 5 //哲学家数目,可改变为其她数目
#define START_POINT 150
#define DESK_DIAMETER 200 //圆桌直径
#define PHIL_DIAMETER 30 //哲学家圆圈直径
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR pszCmdLine, int nCmdShow )
{
static char szAppName[]="哲学家进餐";
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
wndClass、style = CS_VREDRAW | CS_HREDRAW ;
wndClass、lpfnWndProc = WindowProc;
wndClass、cbClsExtra = 0;
unsigned int __stdcall DineMany(LPVOID pParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR pszCmdLine, int nCmdShow );
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsgId,WPARAM wParam, LPARAM lParam );
4实现程序
#include<windows、h>
#include <process、h>
#include<math、h>
#include<time、h>
#define DEGRESS_TO_RADIAN(x) (x) * 3、14 / 180
typedef struct
{
HWND hWnd; //窗口句柄
图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所示。
图14设置成多线程环境完成设置后单击OK按钮关闭Project Settings对话框。
(5)编译运行单击Build菜单中得Rebuild All菜单项编译项目,或者单击工具栏中Build Minibar工具
栏得Build工具按钮编译项目。Build Minibar工具栏形状为,Build
工具按钮对应得图标为,对应得快捷键就是F7。
#define CHOP_LENGHT 50 //筷子长度
#define TIME 10000 //持续时间长度
int chopSticks[PHIL_NUM]; //筷子得初态
int Finished[PHIL_NUM]; //用餐就是否完成
HANDLE hMutex; //互斥量
HANDLE hEvent; //事件
图12显示新项目信息
单击New Project Information对话框中得OK按钮,关闭New Project Information对话框,项目建立步骤完成。
(2)建立文件单击File菜单中得New菜单项,弹出New对话框。在New对话框中单击Files标签,切换至Files标签页;在Files标签页得文件列表中选择C++ Source File选项,在File输入框中输入文件名。New对话框设置如图13所示。