`
胖好汉
  • 浏览: 6303 次
社区版块
存档分类
最新评论

哲学家

 
阅读更多

哲学家就餐问题是经典的进程同步问题,而以下解决思路也堪称经典。 

 

n  哲学家进餐问题

n  解决思路1:只允许4位哲学家同时拿筷子。此时必然有一个哲学家能拿到2根筷子。

n  如何保证只有4位哲学家同时拿筷子?

n  可以设置一个初值为4的资源信号量。比如,4张椅子,哲学家进餐之前必须先拿到椅子才能做到桌前拿筷子。进餐完毕后,不但要释放筷子,还要释放椅子。

n  哲学家进餐问题

n  解决思路1:只允许4位哲学家同时拿筷子。此时必然有一个哲学家能拿到2根筷子。

n  var chopstick: array[0…4] of semaphore :=(1,1,1,1,1);

n      chair: semaphore := 4;

n  philosopher(i): begin

n    repeat

n      think;

n      wait(chair); //拿椅子

n      wait(chopstick[i]);

n      wait(chopstick[(i+1) mod 5]);                                        

n      eat;                                      

n      signal(chopstick[i]);                     

n      signal(chopstick[(i+1) mod 5]);

n      signal(chair);//释放椅子                  

n    until false;

n  end

n  哲学家进餐问题:解决思路1

n  椅子这种资源信号量可以减少个数。极端的情况是chair初值为1,即只有一把椅子,那么每次只允许一个哲学家进餐,肯定不会饿死,但是效率低。

 

n  哲学家进餐问题:

n  解决思路2:只有哲学家同时能够拿起左右两边的筷子的时候,才允许拿筷子。

n  此思路最简单的办法是用AND信号量解决。不过本次我们考虑用记录型信号量解决的办法。

n  关键词:原子操作。我们想办法使得哲学家拿左边和右边筷子的过程变得不受打扰。

n  哲学家进餐问题:解决思路2

n  如何让拿两边筷子的动作变成一个原子操作?

n  桌边配备一名服务员,饥饿时招呼一个服务员过来帮哲学家拿筷子。服务员拿完左右两边的筷子就可以去帮助其他人服务。

n  哲学家进餐问题

n  解决思路2:只有哲学家同时能够拿起左右两边的筷子的时候,才允许拿筷子。

n  var chopstick: array[0…4] of semaphore :=(1,1,1,1,1);

n      mutex := 1;

n  philosopher(i): begin

n    repeat

n      think;

n      wait(mutex); //招呼服务员过来

n      wait(chopstick[i]);

n      wait(chopstick[(i+1) mod 5]);

n          signal(mutex);//服务员拿完筷子可以给其他人服务                                     

n      eat;                                      

n      signal(chopstick[i]);                     

n      signal(chopstick[(i+1) mod 5]);        

n    until false;

n  end

n  哲学家进餐问题:解决思路2

如果释放服务员的操作在释放筷子之后进行,而不是在吃饭前进行,则演变成了竞争椅子的极端情况(1把椅子)

n  哲学家进餐问题:解决思路2

n  这种方法的问题:假设0号哲学家正在用餐,此时1号和2号哲学家饥饿了,两者同时招呼服务员。最终服务员为1号服务,但因被0号哲学家占用的1号筷子未释放,因此1号哲学家无法就餐,但他也没有释放服务员。本来2号哲学家有机会吃饭的,但因为没有招呼到服务员,因此必须等待。

n  哲学家进餐问题:解决思路2

n  解决该问题的方法:服务员只有在确认左右两边哲学家都没就餐时才会帮该哲学家拿筷子,否则该哲学家释放服务员。

下面用类C实现这种方法,在该方法中,不使用筷子信号量,而是为每个哲学家设置一个状态位,该状态位可以为THINKINGEATING状态。状态位必须被互斥访问。

 

#define N 5  //哲学家数

#define LEFT (i+N-1) % N //i个哲学家左邻居编号

#define RIGHT (i+1) % N //右邻居编号

#define THINKING 0  //思考状态

#define EATING 1     //吃饭状态

int state[N]; // 定义哲学家状态,初始值为0,即思考状态

semaphore mutex =1; //状态位的互斥信号量

void philosopher(int i){

  while(true){

    think();

    take_chop(i);//拿两支筷子

    eat();

    put_chop(i);//放下两支筷子

  }

}

 

void take_chop(int i){

  wait(mutex);//进入临界区

  if((state[LEFT]!=EATING) && (state[RIGHT]!= EATING)){

    state[i]=EATING;//如果左右两边哲学家都没吃饭,则i可吃饭

  }

  signal(mutex);

}

void put_chop(int i){

  wait(mutex);

  state[i] = THINKING;//吃完饭释放筷子

  signal(mutex);

}

 

 

n  哲学家进餐问题:

n  解决思路3:奇数号哲学家先拿左边筷子,偶数号哲学家先拿右边筷子。(或者相反)

n  此时五位哲学家总是先竞争奇数号筷子,获得后再竞争偶数号筷子。

n  var chopstick: array[0…4] of semaphore :=(1,1,1,1,1);

n  philosopher(i): begin

n    repeat

n      think;

n      wait(chopstick[(i+(i+1) mod 2) mod 5]);

n      wait(chopstick[(i+(i mod 2)) mod 5]);

n      eat;                                      

n      signal(chopstick[(i+(i+1) mod 2) mod 5]);      

n      signal(chopstick[(i+(i mod 2)) mod 5]);

n  until false;

n  end

n  哲学家进餐问题:解决思路3

n  思路3的一些变种:

n  任意一位哲学家与其他哲学家反方向申请筷子

先拿筷子的三位哲学家与后面两位哲学家反方向申请筷子。

分享到:
评论

相关推荐

    哲学家进餐.c

    哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有...

    哲学家就餐(死锁与非死锁解法)(图形界面)

    在 windows 环境下,利用高级语言编程环境(限定为 VS 环境或 VC 环境或QT)调用 CreateThread 函数哲学家就餐问题的演示。要求:(1)提供死锁的解法和非死锁的解法;(2)有图形界面直观显示哲学家取筷子,吃饭,...

    哲学家就餐问题与死锁

    假设有几位哲学家围坐在一张餐桌旁,桌上有吃不尽的食品,每两位哲学家之间摆放着一根筷子,筷子的个数与哲学家的数量相等,每一位哲学家要么思考,要么等待,要么拿起左右两根筷子进餐。本设计假设有五个哲学家和五...

    操作系统 实验报告(含代码) 死锁和饥饿2 哲学家就餐问题

    哲学家的生活就是思考和吃饭,即思考,饿了就餐,再思考,循环往复。要求是: 每一个哲学家只有在拿到位于他左右的筷子后,才能够就餐;哲学家只能先拿左边的筷子,再去拿右边的筷子,而不能同时去抓他两边的筷子,...

    基于Java窗体实现的模拟哲学家进餐演示系统.zip

    实现一个模拟哲学家进餐问题的系统,要求用户选用哪一种算法进行哲学家进餐演示。 Main 类:初始化主界面类,它结合 javaFx 提供的可图化界面设计来设计主界面 MainController 类:处理主界面鼠标选择事件的类,用来...

    课程设计哲学家就餐问题(报告+代码)C++语言

    设有五个哲学家,共用一张放有五把椅子的餐桌,每人坐在一把椅子上,桌子上有五个碗和五只筷子,每人两边各放一只筷子。哲学家们是交替思考和进餐,饥饿时便试图取其左右最靠近他的筷子。条件: (1) 只有拿到两只筷子时,...

    哲学家.zip使用Linux线程信号量实现哲学家问题

    使用Linux线程信号量实现哲学家问题,只用信号量和互斥量。问题描述:由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共用一张圆桌,分别坐在...

    操作系统 哲学家进餐问题 实现 1 输入饥饿哲学家 2 停止就餐 3 显示个哲学家的状态

    用c++实现哲学家进餐问题 哲学家i思考中 1 输入饥饿哲学家 2 停止就餐 3 显示个哲学家的状态 "饥饿哲学家的数目 各饥饿哲学家的编号 输入释放筷子的哲学家编号

    java实现哲学家进餐问题

    有五个哲学家,他们的生活方式是交替地进行思考和进餐。他们共用一张圆桌,分别坐在五张椅子上。 在圆桌上有五个碗和五把叉子,平时一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两...

    哲学家进餐C++程序

    规则:五个哲学家,他们交替地进行思考和进餐。他们分别坐在位于一个圆形餐桌周围的五把椅子上,餐桌上共有五根筷子,分别摆放在每两个相邻座位的中间。当哲学家思考时,他不与其他人交谈。当哲学家饥饿时,他将拿起...

    哲学家多线程

    哲学家多线程 java

    ucos-3实现哲学家就餐问题

    用最新的ucos-3来实现哲学家就餐的问题。5个哲学家围坐在桌子周围,实现哲学家的有序就餐,并避免死锁

    哲学家进餐问题死锁的造成.cpp

    死锁的四个条件: (1) 互斥条件:一个资源每次只能被一个进程使用。 (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。...当所有哲学家同时决定进餐,拿起左边筷子时候,就发生了死锁。

    哲学家就餐问题源程序

    关于5个哲学家就餐线程同步问题的解决方法 此方法对左右手刀叉实行控制,防止了死锁,实现了线程的同步 注意5个以上的哲学家亦可用此方法解决

    C# 哲学家就餐问题的模拟

    1. 使用信号量的方式模拟哲学家就餐问题。 2. 用一个输入变量控制是否有左撇子哲学家。如果有,其数量由随机数生成。 3. 模拟程序分为两种情况, (1) 可能发生死锁的情况,输出发生死锁时的资源分配状态和历史资源...

    操作系统 哲学家进餐进程算法

    实验一 进程同步互斥——不死锁的哲学家问题  (1)输入的形式和输入值的范围;  由于这个是一个按钮实现监控,界面提供视图的程序,所以并不需要别的附加的输入,只需要点击相应的按钮即可。按钮有开始、暂停、结束...

    哲学家进餐问题的代码

    有三个.cpp文件,代码是我亲手写的,都可以运行,这个代码包含有3种方式避免死锁的方法,一个是允许四个哲学家同时进餐,第二个是一下子就拿两根筷子,否则不拿,第三个就是奇数哲学家先拿左边的筷子,偶数哲学家拿...

    哲学家进餐源代码

    实验一 进程同步互斥——不死锁的哲学家问题  (1)输入的形式和输入值的范围;  由于这个是一个按钮实现监控,界面提供视图的程序,所以并不需要别的附加的输入,只需要点击相应的按钮即可。按钮有开始、暂停、...

    哲学家吃饭问题C++编程实现

    哲学家吃饭问题 c++编程 操作系统 实例

    操作系统实验代码 (哲学家问题,读写问题)

    有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人 之间放一只筷子每个哲学家的行为是思考,感到饥饿,然后吃通心粉.为了吃通心粉,每 个哲学家必须拿到两只筷子,并且每个人只能直接...

Global site tag (gtag.js) - Google Analytics