操作系统原理:哲学家就餐经典问题
哲学家就相当于线程,叉子就相当于资源。每个线程需要获取特定的两个资源才可以执行“吃”操作。每个叉子只能被特定的两个线程访问,且访问叉子时是互斥的。假设数据结构设计一个信号量数组,5个元素代表5个叉子,每个信号量的初始值(最大值)为1 代表每个叉子只能被1个线程同时访问 ,即互斥。0号线程只能访问0号资源和1号资源,1号线程只能访问1号资源和2号资源......4号线程只能访问4号资源和0号资源。
那么有人这么设计,每个哲学家先拿右边的叉子,再拿左手边的叉子。如果无法同时拿起两个叉子就释放掉自己占用的资源。
这个算法有一定的缺陷,如果线程/进程的时间片大小和 takefork(i) 执行的时间一致,那么当CPU执行完“先拿右边的叉子”后时间片用完,切换到下一个就绪线程执行“先拿右边的叉子”...到最后所有线程都拿起了右边的叉子,无法拿起左边的叉子,最后有可能再一同释放,不断循环....
如果再此基础上添加一个条件,如果我要尝试拿叉子的时候把左右两个叉子一起锁住呢?如果锁不住就释放锁。即要么两个一起拿,要么就不拿叉子进入等待。
怎么实现呢,先理一理规则。
当自己需要进食的时候,需要判断左边的叉子和右边叉子的状态是否可用。如果可用则消耗掉这两把叉子资源,不可用则进行等待。所以,需要一个叉子的状态数组状态分为可用和不可用,由于数组本身的访问不具有互斥性,所以还需要一个互斥量来保护状态数组的访问;
#define N 5
#define LEFT i
#define RIGHT (i+1)%N
#define FREE 0
#defind USED 1
int state[N]; //记录每个叉子的状态,初始值为FREE
semaphore mutex ; //保护state[]的互斥访问,初始值为1void philosopher(int i ) //第i个哲学家需要拿第i号和(i+1)%N号的叉子
{bool couldeat = false;while(!couldeat){P(mutex); //访问state前需要Pif(state[LEFT] == FREE && state[RIGHT ] == FREE){state[LEFT ] = USED ;state[RIGHT ] = USED ;V(mutex); //访问state完才可以释放couldeat = true;}else{V(mutex);....hunger(i); // 哲学家自身进入饥饿(阻塞)状态}}....eat()...... //获取到两把叉子就可以执行自己的私有操作了P(mutex); //访问state前需要Pstate[LEFT ] = FREE ;state[RIGHT ] = FREE ;//如果左边的左边叉子可用,那么通知左边的哲学家可以就餐if( state[(LEFT - 1)%N] ==FREE){notice(LEFT);}//如果右边的右边叉子可用,那么通知右边的哲学家可以就餐if( state[(RIGHT + 1)%N] ==FREE){notice(RIGHT );}V(mutex);
}
上述代码是一叉子为资源的一个伪码。如果以哲学家为资源的呢代码该如何呢?思路是一样的,用一个状态数组表示哲学家的3种状态,思考、饥饿、就餐。其中,隔壁的哲学家在就餐意味着自己无法就餐,进入阻塞态。隔壁没有哲学家就餐才意味着自己身边的两个叉子可用。
其中用一个函数判断i号哲学家满不满足吃饭资格的函数:
void test_take_left_right_forks(int i){if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING){//当隔壁的哲学家不在吃饭且自己处于饥饿时唤醒第i号哲学家就餐state[i] == EATING;V(s[i]);}}
代码框架如下图,主要需要实现的是take_forks(i);和 put_forks(i). ,think() 和 eat()是自己的私有操作。
void take_forks(int i ) { // i号哲学家试图拿叉子P(mutex);state[i] = HUNGRY; //让自己为饥饿状态test_take_left_right_forks(i); //如果没叉子那么s[i]==0,有叉子则s[i] ==1V(mutex);P(s[i]); //没有叉子则阻塞自身
}void put_forks(int i ) { // i号哲学家吃完并通知隔壁的哲学家P(mutex);state[i] = THINKING; //自己不处于吃饭状态啦!!!test_take_left_right_forks(LEFT); //因为自己吃饭导致隔壁哲学家饥饿(阻塞),所以要尝试唤醒他test_take_left_right_forks(RIGHT); //右边也一样V(mutex);}
操作系统原理:哲学家就餐经典问题相关推荐
- 【操作系统】哲学家就餐问题
问题 有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子.每个哲学家的行为是思考,感到饥饿,然后吃通心粉.为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只 ...
- 【操作系统/OS笔记14】经典同步问题:读者-写者问题、哲学家就餐问题
本次笔记内容: 10.6 经典同步问题-1 10.7 经典同步问题-2 10.8 经典同步问题-3 10.9 经典同步问题-4 10.10 经典同步问题-5 10.11 经典同步问题-6 文章目录 读 ...
- 操作系统 | PV操作七大经典问题 生产者消费者 读者写者 哲学家进餐 理发师理发睡觉 和尚打水 吸烟者 吃水果
一.生产者消费者问题 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案 ...
- 操作系统(四) | 经典进程的同步问题(生产者--消费者问题、哲学家进餐问题、读者--写者问题)
文章目录 生产者--消费者问题 分析 实现 哲学家进餐问题 方法一:最多4人同时拿左筷子,最终保证一人能进餐 方法二:同时给左右筷子 解法1:AND信号量 解法2:信号量保护机制 方法三:让奇数先左后 ...
- 全国计算机四级——操作系统原理笔记
学习建议:结合书和笔记把知识过一遍 -> 买题库刷试卷 -> 始终学不明白的题目去刷章节题目 -> 背新增试卷题目 关于本笔记:写者参加2022年5月的考试,参考<全国计算机等 ...
- 操作系统原理总结,非科班必看!!!
操作系统原理总结 一.操作系统概述 1.操作系统概念 2.操作系统的基本功能 二.处理机管理 1.作业的概念 2.作业的过程 3.单道批处理系统的作业调度算法 4.进程的概念 5.进程和程序的区别和联 ...
- 计算机网络 本 课程导学,课程导学 - 操作系统原理 - 浙江大学网络教育精品资源共享课...
课程名称:操作系统原理授课时数:32学时 面向对象:计算机科学与技术专业 预修课程要求:C/C++程序设计语言.数据结构 一.课程介绍 操作系统是一门理论与实践并重的专业核心课程.本课程的主要任务是帮 ...
- 【操作系统原理要点笔记 附带英文词汇】
Command-Line(CLI),GraphicsUserInterface(GUI),Batch命令行(CLI).图形用户界面(GUI).批处理 manipulation操纵 facilities ...
- 哲学家就餐 linux实现_Linux哲学的9个主要原则如何影响您
哲学家就餐 linux实现 上一次,我在Linux哲学的影响中讨论了Linux哲学的较高层次的观点. 关于它有一些非常好的讨论,许多博客联合了Opensource.com. 我从上一篇文章中收到的评论 ...
最新文章
- jQuery学习笔记之extend方法小结
- LaTeX:公式及编号
- internal server error怎么解决_MAC中MySQL添加my.cnf和PID file解决方案
- C# 关于MVC框架的简单实例(计算器)
- bat(续六)-windows批处理set命令
- 【Siddhi】Siddhi 如何表示布尔 Syntax error in SiddhiQL, mismatched input ‘boolean
- Golang 删除切片指定元素
- C#中将字符串中某字符不区分大小写并按全字匹配替换为空
- DGIOT物联网开源平台——腾讯云轻量应用服务器部署
- 微信小程序view居中问题
- GPS 经纬度转换 百度、高德经纬度
- android分享微信获取资源失败怎么办,Android处理使用Intent分享图片,以及在微信7.0版本出现“获取资源失败,无法分享到朋友圈”,导致分享失败的问题...
- NGUI-动画Tween
- mysql 手工配置_小姜学网络(MySQL数据库的手工安装与配置)附代码
- ppt文件太大如何压缩变小?
- 如何使用Mezzanine
- Qt中文乱码原因及解决方案
- unordered_set使用介绍
- 入网许可证_入网许可证
- 大数据需要学习哪些技术?