哲学家进餐

问题描述

一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭,如图2-10所示。哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿的时候,才试图拿起左、 右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。

问题分析

1) 关系分析。5名哲学家与左右邻居对其中间筷子的访问是互斥关系。

2) 整理思路。显然这里有五个进程。本题的关键是如何让一个哲学家拿到左右两个筷子而不造成死锁或者饥饿现象。那么解决方法有两个,一个是让他们同时拿两个筷子;二是对每个哲学家的动作制定规则,避免饥饿或者死锁现象的发生。

图2-10 5名哲学家进餐

3) 信号量设置。定义互斥信号量数组Ch0PstiCk[5] = {l, 1, 1, 1, 1}用于对5个筷子的互斥访问。

对哲学家按顺序从0~4编号,哲学家i左边的筷子的编号为i,哲学家右边的筷子的编号为(i+l)%5。

  1. semaphore chopstick[5] = {1,1,1,1,1}; //定义信号量数组chopstick[5],并初始化
  2. Pi(){ //i号哲学家的进程
  3. do{
  4. P (chopstick[i] ) ; //取左边筷子
  5. P (chopstick[(i+1) %5] ) ; //取右边篌子
  6. eat; //进餐
  7. V(chopstick[i]) ; //放回左边筷子
  8. V(chopstick[(i+l)%5]); //放回右边筷子
  9. think; //思考
  10. } while (1);
  11. }

该算法存在以下问题:当五个哲学家都想要进餐,分别拿起他们左边筷子的时候(都恰好执行完wait(chopstick[i]);)筷子已经被拿光了,等到他们再想拿右边的筷子的时候(执行 wait(chopstick[(i+l)%5]);)就全被阻塞了,这就出现了死锁。

为了防止死锁的发生,可以对哲学家进程施加一些限制条件,比如至多允许四个哲学家同时进餐;仅当一个哲学家左右两边的筷子都可用时才允许他抓起筷子;对哲学家顺序编号,要求奇数号哲学家先抓左边的筷子,然后再转他右边的筷子,而偶数号哲学家刚好相反。正解制定规则如下:假设釆用第二种方法,当一个哲学家左右两边的筷子都可用时,才允许他抓起筷子。

  1. semaphore chopstick[5] = {1,1,1,1,1}; //初始化信号量
  2. semaphore mutex=l; //设置取筷子的信号量
  3. Pi(){ //i号哲学家的进程
  4. do{
  5. P (mutex) ; //在取筷子前获得互斥量
  6. P (chopstick [i]) ; //取左边筷子
  7. P (chopstick[ (i+1) %5]) ; //取右边筷子
  8. V (mutex) ; //释放取筷子的信号量
  9. eat; //进餐
  10. V(chopstick[i] ) ; //放回左边筷子
  11. V(chopstick[ (i+l)%5]) ; //放回右边筷子
  12. think; // 思考
  13. }while(1);
  14. }

此外还可以釆用AND型信号量机制来解决哲学家进餐问题,有兴趣的读者可以查阅相关资料,自行思考

时间: 2024-08-07 20:39:09

哲学家进餐的相关文章

哲学家进餐问题

先直接上代码 1 #define N 5 /* 哲学家数目 */ 2 #define LEFT (i+N-1)%N /* i的左邻编号 */ 3 #define RIGHT (i+ 1)%N /* i的右邻编号 */ 4 #define THINKING 0 /* 哲学家在思考 */ 5 #define HUNGRY 1 /*哲学家试图拿起叉子 */ 6 #define EATING 2 /* 哲学家进餐 */ 7 typedef int semaphore; /*信号量 */ 8 int st

【操作系统】经典的同步问题(生产者消费者问题, 哲学家进餐问题, 读写问题)

用专业术语来说, 进程是程序的一次动态执行.说简单点, 就是进程是系统中的某个任务.操作系统中有多个任务需要执行, 那么怎样执行才能使它们同步呢? 即如何让任务并发执行互不影响呢? 这就引出了进程同步中的经典问题: 生产者消费者问题, 哲学家进餐问题, 读写问题 生产者-消费者问题 有一群生产者进程在生产产品, 并将这些产品提供给消费者进程取消费. 为使生产者进程与消费者进程能并发进行, 在两者间设置了一个具有n个缓冲区的缓冲池, 生产者进程将其所生产的产品翻入缓冲区中, 消费者进程可从一个缓冲

利用Linux下的pthread_mutex_t类型来实现哲学家进餐问题

首先说一下什么是哲学家进餐问题,这是操作系统课程中一个经典的同步问题, 问题如下:如上图,有6个哲学家和6根筷子(那个蓝色部分表示哲学家,那个紫色长条部分表示筷子),他们分别被编了0~5的号!如果某个哲学家想要进餐的话,必须同时拿起左手和右手边的两根筷子才能进餐!哲学家进餐完毕之后,就放下手中拿起的两根筷子!这样其他哲学家就能拿这些筷子进餐了!注意这个哲学家的个数必须是偶数个! OK,这样就可能存在一个死锁问题,比如0号哲学家拿了0号筷子,1号哲学家拿了1号筷子!如此往复,最终的结果就是每个哲学

【ThinkingInJava】63、哲学家进餐问题

/** * 书本:<Thinking In Java> * 功能:哲学家进餐问题 * 作为哲学家,他们很穷,所以他们只能买五根筷子.他们围坐在桌子周围,每人之间放一根筷子.当一个哲学家要就餐的时候了,这个哲学家必须同时得到左边 * 和右边的筷子.如果一个哲学家左边或右边的筷子已经有人在使用筷子了,那么这个哲学家就必须等待,直至可以得到必须的筷子 * 文件:Chopstick.java * 时间:2015年5月9日15:08:21 * 作者:cutter_point */ package Les

java笔记--超级类Object多线程的应用+哲学家进餐算法内部类与多线程结合

关于Object类中的线程方法: Object类是所有Java类的 父类,在该类中定义了三个与线程操作有关的方法,使得所有的Java类在创建之后就支持多线程 这三个方法是:notify(),notifyAll(),wait(),这几个方法都是用来控制线程的运行状态的. 方法列表如下: notify() : 唤醒在此对象监视器上等待的单个线程 notifyAll() : 唤醒在此对象监视器上等待的所有线程 wait() : 在其他线程时调用此对象的notify()或者notifyAll()方法前,

【操作系统总结】哲学家进餐问题

哲学家进餐问题 问题:有五个哲学家公用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,平时一个哲学家进行思考,饿的时候便取用左右做靠近他的筷子,只有他拿到两只筷子时才能进餐,进餐完毕继续思考 利用记录型信号量解决问题 semaphore chopstick[5] = {1, 1, 1, 1, 1};//每一个筷子一个信号量 do { wait(chopstick[i]);//首先这个筷子能不能拿到,否则自我阻塞 wait(chopstick[(i + 1) % 5]);//再判断

Java总结(十)—实现Runnable接口创建线程,线程安全同步,死锁(哲学家进餐问题),读写锁

一.通过实现Runnable接口创建线程 定义实现Runnable接口的类 (1)Runnable接口中只有一个方法public void run();用来定义线程运行体: class MyRun implements Runnable(){ public void run(){ 线程执行的具体代码 } } (2)创建线程的实例的时候将这个类的实例作为参数传递到线程实例内部.然后再启动: Thread thread=new Thread(new MyRun()); Thread.start();

经典进程的同步问题之——哲学家进餐

哲学家进餐问题描述 由Dijkstra提出并解决哲学家进餐问题(The Dinning Philosophers Problem)是经典的同步问题.该问题是描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在桌子上有五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐.平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有他拿到两只筷子时才能进餐,进餐完毕继续进行思考. 1 利用记录型信号量解决哲学家进餐问题 经过分析可知,圆桌上的筷子是临界资源,在一段时间内只允许一位哲学

信号量解决哲学家进餐问题

参考线程同步之信号量(sem_init,sem_post,sem_wait) - 郑志强Aloha - 博客园 以及<操作系统概念>第七版 第六章 项目:生产者-消费者问题 题目描述: 哲学家进餐问题描述有五个哲学家,他们的生活方式是交替地进行思考和进餐,n哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,n平时哲学家进行思考,饥饿时便试图取其左.右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,n进餐完毕,放下筷子又继续思考. 如图. 编号都为0-4.哲学家0-3左