哲学家进餐问题:

(1) 在什么情况下5 个哲学家全部吃不上饭?
考虑两种实现的方式,如下:
A.算法描述:

 void philosopher(int i) {/*i:哲学家编号,从0 到4*/
while (TRUE) {
think( ); /*哲学家正在思考*/
take_fork(i); /*取左侧的筷子*/
take_fork((i+) % N); /*取左侧筷子;%为取模运算*/
eat( ); /*吃饭*/
put_fork(i); /*把左侧筷子放回桌子*/
put_fork((i+) % N); /*把右侧筷子放回桌子*/
}
}

分析:假如所有的哲学家都同时拿起左侧筷子,看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子,如此这般,永远重复。对于这种情况,即所有的程序都在无限期地运行,但是都无法取得任何进展,即出现饥饿,所有哲学家都吃不上饭。
B.算法描述:
规定在拿到左侧的筷子后,先检查右面的筷子是否可用。如果不可用,则先放下左侧筷子,等一段时间再重复整个过程。分析:当出现以下情形,在某一个瞬间,所有的哲学家都同时启动这个算法,拿起左侧的筷子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此这样永远重复下去。对于这种情况,所有的程序都在运行,但却无法取得进展,即出现饥饿,所有的哲学家都吃不上饭。

(2) 描述一种没有人饿死(永远拿不到筷子)算法。
考虑了四种实现的方式(A、B、C、D):
A.原理:至多只允许四个哲学家同时进餐以保证至少有一个哲学家能够进餐最终总会释放出他所使用过的两支筷子从而可使更多的哲学家进餐。以下将room作为信号量,只允许4个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会出现饿死和死锁的现象。
伪码:

 semaphore chopstick[]={,,,,};
semaphore room=;
void philosopher(int i) {
while(true) {
think();
wait(room); //请求进入房间进餐
wait(chopstick[i]); //请求左手边的筷子
wait(chopstick[(i+)%]); //请求右手边的筷子
eat();
signal(chopstick[(i+)%]); //释放右手边的筷子
signal(chopstick[i]); //释放左手边的筷子
signal(room); //退出房间释放信号量room
}
}

B.原理:仅当哲学家的左右两支筷子都可用时才允许他拿起筷子进餐。方法1:利用AND型信号量机制实现:根据课程讲述,在一个原语中,将一段代码同时需要的多个临界资源,要么全部分配给它,要么一个都不分配,因此不会出现死锁的情形。当某些资源不够时阻塞调用进程;由于等待队列的存在,使得对资源的请求满足FIFO 的要求,因此不会出现饥饿的情形。
伪码:

 semaphore chopstick[]={,,,,};
void philosopher(int I) {
while(true) {
think();
Swait(chopstick[(I+)]%,chopstick[I]);
eat();
Ssignal(chopstick[(I+)]%,chopstick[I]);
}
}

方法2:利用信号量的保护机制实现。通过信号量mutex对eat()之前的取左侧和右侧筷子的操作进行保护,使之成为一个原子操作,这样可以防止死锁的出现。
伪码:

 semaphore mutex =  ;
semaphore chopstick[]={,,,,};
void philosopher(int I) {
while(true) {
think();
wait(mutex);
wait(chopstick[(I+)]%);
wait(chopstick[I]);
signal(mutex);
eat();
signal(chopstick[(I+)]%);
signal(chopstick[I]);
}
}

C. 原理:规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号的哲学家则相反.按此规定,将是12号哲学家竞争1号筷子34号哲学家竞争3号筷子.即五个哲学家都竞争奇数号筷子获得后再去竞争偶数号筷子最后总会有一个哲学家能获得两支筷子而进餐。而申请不到的哲学家进入阻塞等待队列,根FIFO原则,则先申请的哲学家会较先可以吃饭,因此不会出现饿死的哲学家。
伪码:

 semaphore chopstick[]={,,,,};
void philosopher(int i) {
while(true) {
think();
if(i% == ) {//偶数哲学家,先右后左。
wait (chopstick[ i + ] mod );
wait (chopstick[ i]);
eat();
signal (chopstick[ i + ] mod );
signal (chopstick[ i]);
}
else { //奇数哲学家,先左后右。
wait (chopstick[ i]);
wait (chopstick[ i + ] mod );
eat();
signal (chopstick[ i]);
signal (chopstick[ i + ] mod );
}
}
}

OS | 哲学家问题的更多相关文章

  1. μC/OS学习资料(附Ebook)

    注意:下载地址位于文末. μC/OS-各版本源码 <嵌入式实时操作系统μC/OS-II> <嵌入式实时操作系统μC/OS-III> <μC/OSII2.52源码中文译注- ...

  2. OS知识点总结

    转自:https://blog.csdn.net/csdn_chai/article/details/78002202 1.什么是操作系统? OS是用户与硬件之间的接口,管理计算机的软件和硬件资源. ...

  3. 菜鸟的飞翔日记-os篇

    一轮王道os复习感想 1概述 虽然去年有上操作系统这门必修课,考的成绩也算理想,本来还有点沾沾自喜,嗯,觉得自己学的还不错,知道有一天我拿起了王道,(没给王道打广告)看王道的原因完全在于为考研做准备, ...

  4. 《Tsinghua os mooc》第17~20讲 同步互斥、信号量、管程、死锁

    第十七讲 同步互斥 进程并发执行 好处1:共享资源.比如:多个用户使用同一台计算机. 好处2:加速.I/O操作和CPU计算可以重叠(并行). 好处3:模块化. 将大程序分解成小程序.以编译为例,gcc ...

  5. [OS] 操作系统课程(三)

    工具 源码阅读:understand 源码文档自动生成工具:Doxygen 编译环境:gcc 运行环境:x86机器或QEMU 调试工具:QEMU+(GDB or IDE) IDE:Eclipse-CD ...

  6. NodeJs之OS

    OS Node.js提供了一些基本的底层操作系统的模块OS. API var os = require('os'); console.log('[arch] 操作系统CPU架构'+os.arch()) ...

  7. Node.js:OS模块

    os模块,可以用来获取操作系统相关的信息和机器物理信息,例如操作系统平台,内核,cpu架构,内存,cpu,网卡等信息. 使用如下所示: const os = require('os'); var de ...

  8. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  9. Mac OS 使用 Vagrant 管理虚拟机(VirtualBox)

    Vagrant(官网.github)是一款构建虚拟开发环境的工具,支持 Window,Linux,Mac OS,Vagrant 中的 Boxes 概念类似于 Docker(实质是不同的),你可以把它看 ...

随机推荐

  1. 卸载Windows服务

    在Windows中,有一类程序称为服务,在操作系统内核加载完成后就开始加载.这里程序往往运行在操作系统的底层,因此资源占用比较大.执行效率比较 高,比较有代表性的就是杀毒软件. 但是一旦因为特殊原因不 ...

  2. 【Qt】学习笔记(一)

    1.setupUi(this) : setupUi(this)是由.ui文件生成的类的构造函数这个函数的作用是对界面进行初始化它按照我们在Qt设计器里设计的样子把窗体画出来 setupUi(this) ...

  3. 优秀前端工程师应该掌握的内容(转自:github)

    程序 标准规范 ECMAScript HTTP 知识储备 作用域/闭包 数据结构 算法 编程范式 函数式 面向对象 基于原型 面向方面 设计模式 软件架构 MVC MVVM 安全 XSS CSRF 富 ...

  4. (九)STM32之AFIO

    也许你以为IO和AFIO是很简单的,事实上有几个误区可能很多人都没注意过,当你只用现成的开发板来学习的时候,别人已经帮你做好了资源分配,所有的外设功能学习都是照着别人给你的例程去做的,这才没让你觉得奇 ...

  5. linux安装gcc

    方法:输入命令: :(1) :yum -y install gcc (2) yum -y install gcc-c++(3)yum install make 我的再输入  yum -y instal ...

  6. Android Session

    AsyncHttpClient保持session http://blog.csdn.net/ewrfedf/article/details/21968511

  7. Android之事件分发机制

    本文主要包括以下内容 view的事件分发 viewGroup的事件分发 首先来看两张图 在执行touch事件时 首先执行dispatchTouchEvent方法,执行事件分发. 再执行onInterc ...

  8. Android之数据库操作

    安卓数据库帮助类 /** * 数据库帮助类,用于管理数据库 * @author Administrator * */ public class PersonSQLiteOpenHelper exten ...

  9. MySQL错误:Every derived table must have its own alias

    Every derived table must have its own alias 派生表都必须有自己的别名 一般在多表查询时,会出现此错误. 因为,进行嵌套查询的时候子查询出来的的结果是作为一个 ...

  10. 电赛菜鸟营培训(一)——STM32F103CB之LED控制

    一.STM32F103C8 引脚分布 二.LED的共阴.共阳接法 这里应该是七段数码管的接法. 限流电阻选择为470,在Multism中仿真,也需要接入,否则会出现闪烁情况.或者直接更改属性. 三.消 ...