并发多线程之死锁-----哲学家吃饭问题
来源:互联网 发布:淘宝开放平台接口 编辑:程序博客网 时间:2024/04/27 15:53
该例子说明了4点出现死锁需要同时满足的条件:
- 互斥条件:任务使用的资源至少有一个是不能共享的。这里,一根chopstick(筷子)一次就只能让一个philosopher(哲学家)使用。
- 至少有一个任务它必须持有一个资源且正在等待获取另一个当前被别的任务持有的资源,也就是说,要发生死锁,philosopher必须拿着一根筷子并且等待另一根筷子。
- 资源不能被任务抢占,任务必须把资源释放当作普通事件。philosopher很有礼貌,他们不会从其他的philosoper那里抢筷子。
必须有循环等待,这时,一个任务等待其他任务所持有的资源,后者又在等待另一个任务所持有的资源,这样一直下去直到有一个任务在等待第一个任务所持有的资源,使得大家都被锁住。在DeadLockingDiningPhilosopher.java中,因为每个philosopher都试图先得到右边的筷子再得到左边的筷子,所以发生循环等待。
因为要发生死锁,所有这些条件都必须满足,要防止死锁的话,破坏其中一个条件即可,在程序中,防止死锁的最容易的方法是破坏第4个条件,即循坏等待条件,本例中,就是最后一个哲学家先拿起左边的筷子,再拿起右边的筷子。这样就可以防止循环等待。
Chockstick.java:筷子定义类
package philo;public class Chopstick { private boolean taken = false; public synchronized void take() throws InterruptedException { //当一个任务拿起该筷子时,将taken赋值true,别的任务就在take()上等待 while(taken) wait(); taken = true; } public synchronized void drop(){ //当持有筷子的任务drop时,taken赋值false,在该筷子对象的taken()上等待的任务就可以获得该筷子 taken = false; notifyAll(); }}
Philosopher.java:哲学家定义类
package philo;import java.util.Random;import java.util.concurrent.TimeUnit;public class Philosopher implements Runnable { private Chopstick left; private Chopstick right; private final int id; private final int ponderFactor; private Random random = new Random(47); private void pause() throws InterruptedException { if(ponderFactor == 0) return; TimeUnit.MILLISECONDS.sleep(random.nextInt(ponderFactor * 250)); } public Philosopher(Chopstick left, Chopstick right, int ident, int ponder){ this.left = left; this.right = right; this.id = ident; this.ponderFactor = ponder; } public void run() { //起一个任务(线程) try { while(! Thread.interrupted()) { System.out.println(this +" " + "thinking"); pause(); System.out.println(this +" " + "grabbing right"); right.take(); //该哲学家首先拿起右边的筷子 System.out.println(this + " " + "grabbing left"); left.take(); // 该哲学家然后拿起左边的筷子,此处可能发生的情况:1、成功拿起;2、等待左边的哲学家drop掉右手的筷子, //若每一个哲学家都拿着右手的等着左手的筷子,并且最后一个哲学家左手等待第一个哲学家右手的筷子,就会循坏等待发生死锁。 System.out.println(this + " " + "is eating");//若该哲学家成功拿起左右手筷子,则吃饭,下一步并释放手中筷子 pause(); right.drop(); left.drop(); } } catch (InterruptedException e) { System.out.println(this + " " + "exiting via interruption"); } } public String toString(){ return "Philosopher" + id; }}
DeadLockingDiningPhilosopher.java :产生死锁的哲学家吃饭main类:including main method
package philo;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class DeadLockingDiningPhilosopher { public static void main(String[] args) throws Exception{ int ponder = 5; if(args.length> 0) ponder = Integer.parseInt(args[0]); int size = 5; if(args.length >1) size = Integer.parseInt(args[1]); ExecutorService exec = Executors.newCachedThreadPool(); Chopstick[] sticks = new Chopstick[size]; for(int i=0; i<size; i++) sticks[i] = new Chopstick(); for(int i =0; i< size; i++) exec.execute(new Philosopher(sticks[i], sticks[(i+1) % size], i, ponder)); //n个哲学家n支筷子循坏使用 if(args.length == 3 && args[2].equals("timeout")) TimeUnit.SECONDS.sleep(5); else { System.out.println("please Press 'Enter' to quit"); System.in.read(); } exec.shutdown(); }}
注:在这里,需要输入命令行参数,一共能三个参数分别是:arg[0]:哲学家思考、吃饭、放下筷子的间隔时间,这里设置为0可以让死锁发生的机会变大;args[1]:哲学家数量;args[2]:timeout暂时没想出用处 .
0 0
- 并发多线程之死锁-----哲学家吃饭问题
- 死锁—哲学家吃饭问题
- java多线程哲学家思考吃饭问题
- 哲学家吃饭问题 代码实现如何 避免线程死锁
- 哲学家吃饭问题
- java 多线程 死锁 哲学家就餐问题
- java 多线程 避免死锁 哲学家就餐问题
- 移动端多线程编程高级篇-哲学家吃饭问题
- 黑马程序员技术博客之哲学家吃饭问题
- 多线程之哲学家就餐问题
- 哲学家吃饭
- Linux 多线程同步之哲学家用餐问题
- Linux 多线程同步之哲学家用餐问题
- Linux 多线程同步之哲学家用餐问题
- 哲学家问题之死锁:A Difficult Philosopher Problem
- 死锁与哲学家就餐问题
- Java并发编程:死锁(哲学家就餐)
- 多线程练习----哲学家问题
- Linux中最受欢迎的邮件传输代理详解
- 详解line-height与vertical-algin
- 电机运行工作制
- 图的邻接表实现
- ZCMU-1309-Vasya and Public Transport
- 并发多线程之死锁-----哲学家吃饭问题
- 在win10上的IIS发布网站问题集锦
- storm四之storm的工作流程
- A1070. Mooncake (25)
- 雪碧图(CSS SPIRIT)简介
- javascript基础:函数传递参数的方式、参数数组、变量范围(变量作用域)
- [LeetCode]410. Split Array Largest Sum
- Linux文件系统和底层驱动的笔记
- Node.js 的模块系统