经典的进程同步问题-----哲学家进餐问题详解
发布日期:2021-06-29 14:52:40
浏览次数:2
分类:技术文章
本文共 3828 字,大约阅读时间需要 12 分钟。
经典的进程同步问题-----哲学家进餐问题详解
一、问题描述
有五个哲学家围在一张圆桌,分别坐在周围的五张椅子上,在圆上有五个碗和木质筷子,他们的生活方式是交替的进行思考和进餐。平时,一个哲学家进行思考,,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕后,放下筷子继续思考。
我们可以得知,筷子是临界资源,同一根筷子同一时刻只能有一个哲学家可以拿到。
二、问题分析
由问题描述我们可以知道,一共有五个哲学家,也就是五个进程:
五只筷子,也就是五个临界资源; 因为哲学家想要进餐,必须要同时获得左边和右边的筷子,这就是要同时进入两个临界区(使用左右两个临界资源),才可以进餐。因为是五只筷子为临界资源,因此设置五个信号量即可
三、 一个错误的例子
首先我们根据之前学习的知识来解决问题,根据上面的分析,我们先给出结论:
semaphore mutex[5] = { 1, 1, 1, 1, 1}; //初始化信号量void philosopher(int i){ do{ // thinking P(mutex[i]) // 判断左边的筷子是否可用 p(mutex[(i+1)%5]); // 判断右边的筷子是否可用 // ... // eat // ... V(mutex[i]); //退出临界区,放下左边的筷子 V(mutex[(i+1)%5]); //退出临界区,放下右边的筷子 }while(true);}
我们来分析下上面的代码,首先我们从一个哲学家的角度来看问题,程序似乎是没有问题的,申请到左右两支筷子后,然后开始进餐。
但是如果考虑到并发问题,五个哲学家同时拿起了左边的筷子,此时,五只筷子立刻都被占用了,没有可用的筷子了,当所有的哲学家再想拿起右边筷子的时候,因为临界资源不足,只能将自身阻塞,而所有的哲学家全部都会阻塞,并且不会释放自己手中拿着的左边的筷子,因此就会一直处于阻塞状态,无法进行进餐并思考。 因为,为了解决五个哲学家争用的资源的问题,我们可以采用以下几种解决方法:
- 至多只允许有四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用餐完毕后能释放他占用的筷子,从而使别的哲学家能够进餐;
- 仅当哲学家的左、右两支筷子可用时,才允许他拿起筷子;
- 规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子;而偶数号哲学家则相反。
下面是我们对每种方法给出的伪代码。
四、 方法一:允许最多四位哲学家拿左边的筷子
对于方法一,至多只允许有四位哲学家同时拿左边的筷子,
我们可以简单的通过增加一个信号量实现,通过这个 信号量限定哲学家并发去进餐的数量。semaphore mutex[5] = { 1, 1, 1, 1, 1};semaphore count = 4; // 最多允许四位哲学家同时进餐void philosopher(int i){ do{ //thinging P(count); // 判断是否超过四个 P(mutex[i]); // 判断缓冲池是否仍有空闲的缓冲区 P(mutex[(i+1)%5]); // 判断缓冲池是否仍有空闲的缓冲区 // ... // eat // ... V(mutex[i]); // 释放空闲的缓冲区 V(mutex[(i+1)%5]); // 释放空闲的缓冲区 V(count); }while(true);}
五、 方法二:使用AND型信号量,同时判断左右的筷子
第二种方法,也就是使用AND型信号量,同时对哲学家左右两边的筷子同时申请。
下面是伪代码:semaphore mutex[5] = { 1, 1, 1, 1, 1}; // 初始化信号量void philosopher(int i){ do{ // thinking Swait(mutex[i], mutex[(i+1)%5]); // 进餐,同时判断左右的筷子 // ... // eat // ... Ssignal(mutex[i] , mutex[(i+1)%5]); // 进餐完毕,释放筷子 }while(true);}
六、 方法三:奇数拿左边筷子,偶数拿右边筷子
规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子;而偶数号哲学家则相反。
伪代码如下:semaphore mutex[5] = { 1, 1, 1, 1, 1}; // 初始化信号量void philosopher(int i){ do{ // thinking if(i%2 == 1){ P(mutex[i]); // 左 P(mutex[(i+1)%5]); // 右 }else{ P(mutex[(i+1)%5]); // 右 P(mutex[i]); // 左 } // ... // eat // ... V(mutex[i]); // 释放空闲的缓冲区 V(mutex[(i+1)%5]); // 释放空闲的缓冲区 }while(true);}
七、 测试
这里我们通过Java模拟实现哲学家进餐问题,这里我们使用方法一(其他几种方式只需修改对应哲学家线程中的代码即可),下面是具体的代码:
import com.alibaba.fastjson.JSON;import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;import java.util.List;import java.util.concurrent.Semaphore;/** * 学者进餐问题 */public class PhilosophersTest { static final Semaphore count = new Semaphore(4); static final Semaphore[] mutex = { new Semaphore(1), new Semaphore(1), new Semaphore(1), new Semaphore(1), new Semaphore(1)}; static class Philosopher extends Thread { Philosopher(String name) { super.setName(name); } @Override public void run() { do { try { count.acquire(); Integer i = Integer.parseInt(super.getName()); mutex[i].acquire(); mutex[(i + 1) % 5].acquire(); log.info("哲学家【{}】号吃了通心粉!", i); mutex[i].release(); mutex[(i + 1) % 5].release(); count.release(); Thread.sleep(5000); } catch (InterruptedException e) { log.error("哲学家执行时产生异常!"); } } while (true); } } public static void main(String[] args) { Philosopher p0 = new Philosopher("0"); Philosopher p1 = new Philosopher("1"); Philosopher p2 = new Philosopher("2"); Philosopher p3 = new Philosopher("3"); Philosopher p4 = new Philosopher("4"); p0.start(); p1.start(); p2.start(); p3.start(); p4.start(); }}
转载地址:https://ciellee.blog.csdn.net/article/details/107482597 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
表示我来过!
[***.240.166.169]2024年04月19日 18时59分55秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
五年,我成为了一名嵌入式工程师。
2019-04-29
2020年电赛题目,命题专家们怎么看?
2019-04-29
PCB元器件摆放不可忽略的10个技巧
2019-04-29
掌握AI核心技术没有秘籍,能自己创造就是王道
2019-04-29
大学老师的月薪多少?实话实说:4万多一点……
2019-04-29
2020年电赛题目,命题专家权威解析!
2019-04-29
写论文,这个神器不能少!
2019-04-29
现在做硬件工程师还有前途吗?
2019-04-29
华为被超越!这家公司成中国最大智能手机制造商,不是小米!
2019-04-29
芯片为什么持续缺货?
2019-04-29
美国无人机在火星首飞成功,创造历史,3米飞行高度悬停30秒
2019-04-29
缺货涨价很久的MCU的国产和国外厂家汇总!(80家)
2019-04-29
华为重磅反击,鸿蒙来了!
2019-04-29
常用电子接口大全,遇到不认识的,就翻出来对照辨认!
2019-04-29
芯片IC附近为啥要放0.1uF的电容?
2019-04-29
电赛 | 19年全国一等奖,北航学子回忆录。
2019-04-29
电赛 | 19年全国一等奖,北航学子回忆录(上)
2019-04-29
电赛 | 19年全国一等奖,北航学子回忆录(下)
2019-04-29
突破!台积电1nm芯片,有了新进展。
2019-04-29
一文读懂全系列树莓派!
2019-04-29