哲学家就餐与死锁问题,死锁产生的条件以及解决方案
来源:互联网 发布:茶叶网络营销策划方案 编辑:程序博客网 时间:2024/06/05 11:59
请结合经典案例-哲学家就餐,来谈谈你对死锁的理解,以及怎么预防和解除死锁?
哲学家就餐
描述:在一张圆桌上,有n个哲学家,n支筷子,他们的生活方式只是交替地进行思考和进餐,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,进餐完毕,放下筷子又继续思考。
根据描述,实现代码如下:
import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class Question17 {public static void main(String[] args) {ExecutorService exec = Executors.newCachedThreadPool();int sum = 5;Chopstick[] chopsticks = new Chopstick[sum];for (int i = 0; i < sum; i++) {chopsticks[i] = new Chopstick(i);}for (int j = 0; j < sum; j++) {exec.execute(new Philosopher(chopsticks[j], chopsticks[(j + 1) % sum], j));}}}// 筷子class Chopstick {// 筷子位置 private int id;// 状态private boolean isUsed = false;public Chopstick(int id) {this.id = id;}// 拿取public synchronized void take() throws InterruptedException {while (isUsed) {wait();}System.err.println(this + " 被使用");isUsed = true;}// 放下public synchronized void drop() {isUsed = false;System.err.println(this + " 被放下");notifyAll();}@Overridepublic String toString() {return "筷子[" + id + "]";}}// 哲学家class Philosopher implements Runnable {private Chopstick left;private Chopstick right;private int id;private Random rand = new Random();public Philosopher(Chopstick left, Chopstick right, int id) {this.left = left;this.right = right;this.id = id;}@Overridepublic void run() {while (!Thread.interrupted()) {try {think();System.out.println(this + " 想吃饭!");eat();} catch (InterruptedException e) {System.err.println(this + " InterruptedException");}}}// 思考private void think() throws InterruptedException {System.out.println(this + " 思考...");TimeUnit.MILLISECONDS.sleep(rand.nextInt(1) * 100);}// 吃饭private void eat() throws InterruptedException {left.take();right.take();System.out.println(this + " 正在吃饭...");TimeUnit.MILLISECONDS.sleep(rand.nextInt(2) * 100);left.drop();right.drop();}@Overridepublic String toString() {return "哲学家[" + id + "]";}}
通过运行结果,我们可以发现,到最后,没有一个哲学家能过同时获取两只筷子吃饭。
二、为什么会产生死锁
死锁问题被认为是线程/进程间切换消耗系统性能的一种极端情况。在死锁时,线程/进程间相互等待资源,而又不释放自身的资源,导致无穷无尽的等待,其结果是任务永远无法执行完成。哲学家问题便是线程资源竞争导致的死锁现象,在程序运行一段时间后,程序所处的状态是n位哲学家(n个线程)都各自获取了一只筷子的状态,此时所有哲学家都想获取第二只筷子去吃饭,但是共享资源n只筷子已经都被n位哲学家握在手里了,彼此想要的筷子都在其他哲学家手中,又没有机制能让任何哲学家放弃握在手中的筷子,从而照成了所有哲学家(所有线程)都在等待其他人手中资源的死锁问题。
产生死锁的四个必要条件:
- 互斥条件:一个资源每次只能被一个线程/进程使用。
- 请求与保持条件:一个线程/进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:线程/进程已获得的资源,在未使用完之前,不能强行剥夺。
- 循环等待条件:若干线程/进程之间形成一种头尾相接的循环等待资源关系。
三、死锁的解除与预防
一般解决死锁的途径分为死锁的预防,避免,检测与恢复这三种。
死锁的预防是要求线程/进程申请资源时遵循某种协议,从而打破产生死锁的四个必要条件中的一个或几个,保证系统不会进入死锁状态。
死锁的避免不限制线程/进程有关申请资源的命令,而是对线程/进程所发出的每一个申请资源命令加以动态地检查,并根据检查结果决定是否进行资源分配。
死锁检测与恢复是指系统设有专门的机构,当死锁发生时,该机构能够检测到死锁发生的位置和原因,并能通过外力破坏死锁发生的必要条件,从而使得并发进程从死锁状态中恢复出来。
对于java程序来说,产生死锁时,我们可以用jvisualvm/jstack来分析程序产生的死锁原因,根治死锁问题。
- 哲学家就餐与死锁问题,死锁产生的条件以及解决方案
- 死锁与哲学家就餐问题
- uc笔记12---竞争与同步,互斥量,信号量,死锁,条件变量,哲学家就餐问题
- 如何防止哲学家就餐问题而引起的死锁
- java 多线程 死锁 哲学家就餐问题
- java 多线程 避免死锁 哲学家就餐问题
- 哲学家就餐问题的分析与解决方案
- 哲学家就餐问题与解决方案
- 经典死锁案例-哲学家就餐
- JavaSE第一百零四讲:哲学家就餐问题、死锁与使用wait及notify方法实现线程之间的相互通信
- Java死锁产生的条件以及解决办法
- 死锁以及死锁产生的原因及条件
- Thinking in Java---从哲学家就餐问题看死锁现象
- Thinking in Java---从哲学家就餐问题看死锁现象
- 产生死锁的条件
- 死锁产生的必要条件以及解决方案
- Java并发编程:死锁(哲学家就餐)
- 死锁&死锁的产生条件&死锁的避免
- WebApi开发爬坑记之·一重写ApiController
- RxJava图文详解,可以说是很全了。
- 【转载】[Android Studio 权威教程]AS添加第三方库的6种方式(Jar,module,so等)
- EasyPlayer RTSP播放器源码解析系列之效率优化方案
- MapReduce中的task数量
- 哲学家就餐与死锁问题,死锁产生的条件以及解决方案
- scala中的偏函数
- Rest ful 设计理念
- 快速排序
- JAVA线程通信
- 欢迎使用CSDN-markdown编辑器
- HDOJ1015 Safecracker(DFS,回溯)
- js 实现选项卡里套选项卡
- Java 设计模式之七:中介者模式