哲学家就餐问题-中断解决
哲学家就餐问题是计算机操作系统课程中一定会拿来作为死锁教材的经典案例。问题描述如下:哲学家吃饭问题:哲学家聚在一起吃饭,假定哲学家人数是五,这五个哲学家坐在一张圆桌上面,每个哲学家的左手旁边都放有一个叉子(fork),那么,这围城一圈的五个哲学家有五个叉子。每个哲学家有三种状态,thinking(思考),trying(尝试去拿叉子吃饭),eating(已经拿起叉子,正在吃饭)。每次吃饭需要两个叉子,也就是哲学家左右手边的叉子。如图1所示。
哲学家吃饭需要两个叉子(吼吼)。
图1
本实验采用了两种解决死锁的机制:
- 通过定时器(Timer)检测死锁,一旦发生死锁,就将哲学家恢复到初始的状态,然后使得哲学家和叉子的状态恢复到初始状态。
- 通过外部中断解决死锁,一旦发生死锁问题,通过外部中断,将哲学家恢复到初始的状态,然后使得哲学家和叉子的状态恢复到初始状态。
定时器(Timer)代码:
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <stdlib.h> 4 #include <sys/wait.h>//为了使用sleep()函数 5 #include <unistd.h> 6 #include <signal.h>//为了产生中断 7 8 //哲学家的数目 9 int Number; 10 11 //声明共享变量fork,其中fork的数目和哲学家数目是相同的 12 struct Fork{ 13 int i;//只有0和1两个值,0代表不能被拿起来,1代表可以被拿起来 14 }; 15 struct Fork *myfork; 16 17 //定义一个philosopher的三个状态 18 #define Thinking 1 19 #define Trying 2 20 #define Eating 3 21 22 struct State{ 23 int sta; 24 int left; 25 int right; 26 }; 27 struct State *state; 28 29 void *EatMeal(); 30 31 32 int totalnumber; 33 void DetectLock(int); 34 void Sig_hander(int); 35 36 //得到参数 37 void GetArg( 38 char* argv[] /*in*/, 39 int* number /*out*/ 40 ); 41 //统计处于tring状态的哲学家的个数 42 int tryingNo; 43 44 //拿起叉子 45 int take_Fork(int i); 46 //放下叉子 47 void put_Fork(int i); 48 49 void main(int argc, char* argv[]) 50 { 51 GetArg(argv, &Number); 52 myfork = (struct Fork *)malloc(Number*sizeof(struct Fork)); 53 state = malloc(Number*sizeof(struct State)); 54 55 tryingNo = 0; 56 //声明进程数组,每一个进程代表一个哲学家 57 pthread_t philosopher[Number]; 58 pthread_t deadLockDetecter; 59 totalnumber = Number; 60 /*初始化每个哲学家的状态*/ 61 int t =0; 62 for(t=0; t< Number; t++) 63 { 64 state[t].sta = Thinking; 65 state[t].left = 0; 66 state[t].right = 0; 67 } 68 69 /*初始化每个勺子是可以使用的*/ 70 int k =0; 71 for(k=0; k<Number; k++) 72 { 73 myfork[k].i = 1; 74 } 75 76 int i; 77 //创建和哲学家数量想对应的进程,并且每个进程开始进行吃饭的活动 78 for( i = 0; i < Number; i++) 79 { 80 //记录当前进程的编号,并传递到Meal()函数中 81 int j = i; 82 pthread_create(&philosopher[i], NULL, EatMeal, &j); 83 printf("I am philosopher %d\n", j); 84 } 85 86 //int k = Number; 87 pthread_create(&deadLockDetecter,NULL, DetectLock,&k); 88 89 //将所有的进程进行Join操作。 90 for( i=0; i < Number; i++) 91 { 92 pthread_join(philosopher[i], NULL); 93 } 94 95 //退出程序 96 pthread_exit(0); 97 98 return ; 99 100 } 101 102 void *EatMeal(int *i) 103 { 104 //记录当前的线程id号 105 int id = *i; 106 107 108 state[id].sta = Thinking; //线程初始化的时候为Thinking 109 110 int leftFork = (id + Number) % Number; 111 int rightFork = (id + Number +1) % Number; 112 113 int mealTime = 5; 114 int mymealTime = 0; 115 while (mymealTime < mealTime) //每个philosopher必须吃得符合规定 116 { 117 if(state[id].sta == Thinking) 118 { 119 sleep(3); 120 state[id].sta = Trying; 121 }else if(state[id].sta == Trying) 122 { 123 124 // sleep(1); 125 if (take_Fork(leftFork)) 126 { 127 myfork[leftFork].i = 0; 128 state[id].left = 1; //自己标识左边的叉子被自己拿到 129 // printf("Phi %d takes left\n",id); 130 } 131 if(take_Fork(rightFork)) 132 { 133 myfork[rightFork].i = 0; 134 state[id].right = 1; //自己标识一下右边的叉子被自己拿到 135 // printf("Phi %d takes right\n",id); 136 } 137 138 printf("Philosopher %d is Trying\n", id); 139 sleep(3); 140 if(!take_Fork(leftFork)&&!take_Fork(rightFork)&&state[id].left==1&& state[id].right==1) 141 { 142 state[id].sta = Eating; 143 } 144 } 145 else 146 { 147 printf("Philosopher %d is Eating\n", id); 148 sleep(3); 149 state[id].left=0; 150 state[id].right=0; 151 state[id].sta = Thinking; 152 put_Fork(leftFork); 153 put_Fork(rightFork); 154 mymealTime++; 155 156 } 157 } 158 159 } 160 161 int take_Fork(int forkid) 162 { 163 if(myfork[forkid].i==0) return 0; 164 else 165 { 166 //myfork[forkid].i = 0; 167 return 1; 168 } 169 } 170 171 void put_Fork(int forkid) 172 { 173 if(myfork[forkid].i==0) 174 { 175 myfork[forkid].i=1; 176 } 177 } 178 179 void GetArg( 180 char * argv[], 181 int* number 182 ) 183 { 184 *number = strtol(argv[1], NULL, 10); 185 } 186 187 void DetectLock( 188 int k) 189 { 190 signal(SIGALRM, Sig_hander); 191 alarm(1); 192 while(1) pause(); 193 } 194 195 void Sig_hander(int sig) 196 { 197 int k = totalnumber;//获取人数 198 int flag = 1; 199 int i = 0; 200 for(i=0; i<k; i++) 201 { 202 if(state[i].sta != Trying) 203 { 204 flag = 0; 205 } 206 } 207 if(flag == 1) 208 { 209 printf("I am timer that dealing with deadlock\n"); 210 int m = 0; 211 for(m=0; m<k; m++) 212 { 213 state[m].sta = Thinking; 214 state[m].left = 0; 215 state[m].right = 0; 216 myfork[m].i = 1; 217 } 218 } 219 220 221 alarm(1); 222 return; 223 224 225 }
View Code
外部中断代码:
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <stdlib.h> 4 #include <sys/wait.h>//为了使用sleep()函数 5 #include <unistd.h> 6 #include <signal.h>//为了产生中断 7 8 //哲学家的数目 9 int Number; 10 11 //声明共享变量fork,其中fork的数目和哲学家数目是相同的 12 struct Fork{ 13 int i;//只有0和1两个值,0代表不能被拿起来,1代表可以被拿起来 14 }; 15 struct Fork *myfork; 16 17 //定义一个philosopher的三个状态 18 #define Thinking 1 19 #define Trying 2 20 #define Eating 3 21 22 struct State{ 23 int sta; 24 int left; 25 int right; 26 }; 27 struct State *state; 28 29 void *EatMeal(); 30 31 32 int totalnumber; 33 void DetectLock(int); 34 void Sig_hander(int); 35 36 //得到参数 37 void GetArg( 38 char* argv[] /*in*/, 39 int* number /*out*/ 40 ); 41 //统计处于tring状态的哲学家的个数 42 int tryingNo; 43 44 //拿起叉子 45 int take_Fork(int i); 46 //放下叉子 47 void put_Fork(int i); 48 49 void main(int argc, char* argv[]) 50 { 51 GetArg(argv, &Number); 52 myfork = (struct Fork *)malloc(Number*sizeof(struct Fork)); 53 state = malloc(Number*sizeof(struct State)); 54 55 tryingNo = 0; 56 //声明进程数组,每一个进程代表一个哲学家 57 pthread_t philosopher[Number]; 58 pthread_t deadLockDetecter; 59 totalnumber = Number; 60 /*初始化每个哲学家的状态*/ 61 int t =0; 62 for(t=0; t< Number; t++) 63 { 64 state[t].sta = Thinking; 65 state[t].left = 0; 66 state[t].right = 0; 67 } 68 69 /*初始化每个勺子是可以使用的*/ 70 int k =0; 71 for(k=0; k<Number; k++) 72 { 73 myfork[k].i = 1; 74 } 75 76 int i; 77 //创建和哲学家数量想对应的进程,并且每个进程开始进行吃饭的活动 78 for( i = 0; i < Number; i++) 79 { 80 //记录当前进程的编号,并传递到Meal()函数中 81 int j = i; 82 pthread_create(&philosopher[i], NULL, EatMeal, &j); 83 printf("I am philosopher %d\n", j); 84 } 85 86 //int k = Number; 87 pthread_create(&deadLockDetecter,NULL, DetectLock,&k); 88 89 //将所有的进程进行Join操作。 90 for( i=0; i < Number; i++) 91 { 92 pthread_join(philosopher[i], NULL); 93 } 94 95 //退出程序 96 pthread_exit(0); 97 98 return ; 99 100 } 101 102 void *EatMeal(int *i) 103 { 104 //记录当前的线程id号 105 int id = *i; 106 107 108 state[id].sta = Thinking; //线程初始化的时候为Thinking 109 110 int leftFork = (id + Number) % Number; 111 int rightFork = (id + Number +1) % Number; 112 113 int mealTime = 5; 114 int mymealTime = 0; 115 while (mymealTime < mealTime) //每个philosopher必须吃得符合规定 116 { 117 if(state[id].sta == Thinking) 118 { 119 sleep(3); 120 state[id].sta = Trying; 121 }else if(state[id].sta == Trying) 122 { 123 124 // sleep(1); 125 if (take_Fork(leftFork)) 126 { 127 myfork[leftFork].i = 0; 128 state[id].left = 1; //自己标识左边的叉子被自己拿到 129 // printf("Phi %d takes left\n",id); 130 } 131 if(take_Fork(rightFork)) 132 { 133 myfork[rightFork].i = 0; 134 state[id].right = 1; //自己标识一下右边的叉子被自己拿到 135 // printf("Phi %d takes right\n",id); 136 } 137 138 printf("Philosopher %d is Trying\n", id); 139 sleep(3); 140 if(!take_Fork(leftFork)&&!take_Fork(rightFork)&&state[id].left==1&& state[id].right==1) 141 { 142 state[id].sta = Eating; 143 } 144 } 145 else 146 { 147 printf("Philosopher %d is Eating\n", id); 148 sleep(3); 149 state[id].left=0; 150 state[id].right=0; 151 state[id].sta = Thinking; 152 put_Fork(leftFork); 153 put_Fork(rightFork); 154 mymealTime++; 155 156 } 157 } 158 159 } 160 161 int take_Fork(int forkid) 162 { 163 if(myfork[forkid].i==0) return 0; 164 else 165 { 166 //myfork[forkid].i = 0; 167 return 1; 168 } 169 } 170 171 void put_Fork(int forkid) 172 { 173 if(myfork[forkid].i==0) 174 { 175 myfork[forkid].i=1; 176 } 177 } 178 179 void GetArg( 180 char * argv[], 181 int* number 182 ) 183 { 184 *number = strtol(argv[1], NULL, 10); 185 } 186 187 void DetectLock( 188 int k) 189 { 190 signal(SIGINT, Sig_hander); 191 sleep(10); 192 return ; 193 } 194 195 void Sig_hander(int sig) 196 { 197 int k = totalnumber;//获取人数 198 int flag = 1; 199 int i = 0; 200 for(i=0; i<k; i++) 201 { 202 if(state[i].sta != Trying) 203 { 204 flag = 0; 205 } 206 } 207 if(flag == 1) 208 { 209 printf("I am timer that dealing with deadlock\n"); 210 int m = 0; 211 for(m=0; m<k; m++) 212 { 213 state[m].sta = Thinking; 214 state[m].left = 0; 215 state[m].right = 0; 216 myfork[m].i = 1; 217 } 218 } 219 220 return; 221 222 223 }
View Code
Post Analysis:
将中断注册到了一个线程中,没有把其写入大主线程中。好吧,这个被老师给黑了。扣分到底!
转载于:https://www.cnblogs.com/SevenwindMa/p/3483823.html
哲学家就餐问题-中断解决相关推荐
- 哲学家就餐问题python解决_关于哲学家就餐问题的分析代码.
①总体思路: 都去拿左边的筷子,并且最后一个人不能去拿筷子(防止大家都拿了左边的筷子,没有右边的筷子,导致死锁了),解决死锁问题的办法就是同时只允许四位哲学家同时拿起同一边的筷子,这样就能保证一定会有 ...
- Java多线程学习四十二:有哪些解决死锁问题的策略和哲学家就餐问题
线上发生死锁应该怎么办 如果线上环境发生了死锁,那么其实不良后果就已经造成了,修复死锁的最好时机在于"防患于未然",而不是事后补救.就好比发生火灾时,一旦着了大火,想要不造成损失去 ...
- 用信号量实现进程互斥示例和解决哲学家就餐问题
用信号量实现进程互斥示例和解决哲学家就餐问题 参考文章: (1)用信号量实现进程互斥示例和解决哲学家就餐问题 (2)https://www.cnblogs.com/alantu2018/p/84731 ...
- python解决哲学家就餐问题(and型信号量)
最近操作系统刚学完这部分内容,老师要求下去自己实践一下,在网上看了看发现用python解决该问题的博文很少,而且好多都是错的,于是就自己写了一段代码 # and型信号量解决哲学家就餐问题 import ...
- 哲学家就餐问题python伪代码_GitHub - doooooit/Dining-philosophers-problem: 哲学家进餐问题的两种解决方法...
哲学家就餐问题 问题描述 哲学家就餐问题(Dining philosophers problem)可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考.吃东西的时候, ...
- Thinking in Java---从哲学家就餐问题看死锁现象
我们知道一个对象可以有synchronized方法或其他形式的加锁机制来防止别的线程在互斥还没释放的时候就访问这个对象.而且我们知道线程是会变成阻塞状态的(挂起),所以有时候就会发生死锁的情况:某个任 ...
- 哲学家就餐问题实验报告
哲学家就餐问题 两个地方应该是pv操作,pv都是操作元语,不可中断 p操作是将信号量-1 v操作是将信号量+1 pv一定要配对使用 哲学家进餐可以通过信号量机制解决,避免死锁 注释如下: test(i ...
- Java基础学习之并发篇:哲学家就餐问题
学习目标 哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步时产生的问题.在1971年,著名的计算机科学家艾兹格·迪科斯彻提出了一个同步问题,即假设有五台计算机都试图访问五份 ...
- 哲学家就餐问题c语言_哲学家就餐问题的一种Python解决方案
哲学家就餐问题一直是多线程同步问题的经典案例,本文中展示了多线程竞争共享资源带来的死锁问题,并介绍了一种简单的解决方案. 哲学家就餐问题 哲学家最擅长的就是思考和吃饭 ,当他们感觉累的时候,就会拿起一 ...
- 哲学家就餐问题--信号量和互斥量预防死锁
哲学家就餐问题可以采取预防死锁的方案,就是使用互斥量和信号量锁定资源. 互斥量: 对资源进行锁定的意思就是说,当一个哲学家使用叉子的时候,他首先要先把叉子锁定,然后,拿起来.这个时候如果别的哲学家也来 ...
最新文章
- 干掉Random:这个类已经成为获取随机数的王者
- python比较数据库表今天跟前一天数据增量,Python 生产环境Mysql数据库增量备份脚本...
- 扎克伯格All in元宇宙,公司更名Meta,「脸」不要了
- Mac版 Android Studio Android Sdk 更新方式
- Comcast以纯文本泄露客户Wi-Fi登录信息,立即更改密码
- 笔记本电脑电源已接通未充电_dell xps15 电源已接通 未充电 维修方法
- Python---二分法查找
- 升级oracle spu,关于Oracle数据库PSU/SPU/BundlePatch的补丁号变化
- LeetCode 481. 神奇字符串(找规律)
- 论文浅尝 | 融入知识的弱监督预训练语言模型
- 深度技术win11 32位全新专业版系统v2021.07
- mac下安装mysql-pyhon_mac下安装MySQL-python模块
- Java把表导出成Excel的代码
- c语言成绩管理系统的作用,C语言实现班级成绩管理系统
- java视频在线播放_Java实现视频网站的视频上传与视频播放功能.doc
- 不同计算机的操作码完全相同,单片机课后习题答案
- 对大数据 数据挖掘和机器学习的认识和理解
- 插件框架篇一之scrollbars
- [Rootkit] dll 隐藏 - VAD
- Visio画出简单的拓扑图