-
假设下面一个场景:
4个哲学家,同坐一张方桌子,共2双筷子,4只筷子;每只放在桌角处,每个哲学家有可能拿到1只,1双,或者没有拿到的情况,只有拿到一双时才能开始用餐;没有一个哲学家能用餐成功的时候就处于僵持状态。
-
使用多线程模拟
public class Philosopher extends Thread{ private String name; private Chopsticks leftChopstick; private Chopsticks rightChopstick; public Philosopher(String name, Chopsticks leftChopstick, Chopsticks rightChopstick) { this.name = name; this.leftChopstick = leftChopstick; this.rightChopstick = rightChopstick; } @Override public void run() { eat(); } public void eat(){ synchronized (leftChopstick){ System.out.println(this.name + "拿起了左手边的"+leftChopstick.getNum()+"号筷子"); synchronized (rightChopstick){ System.out.println(this.name + "拿起了右手边的"+rightChopstick.getNum()+"号筷子"); System.out.println("==============================>"+this.name + "开始吃饭了!"); } } } }
public class Chopsticks { private int num; public Chopsticks(int num){ this.num = num; } public int getNum() { return num; } }
测试:
public class TestMain { public static void main(String[] args) { Chopsticks c1 = new Chopsticks(1); Chopsticks c2 = new Chopsticks(2); Chopsticks c3 = new Chopsticks(3); Chopsticks c4 = new Chopsticks(4); Philosopher p1 = new Philosopher("哲学家A",c4,c3); Philosopher p2 = new Philosopher("哲学家B",c3,c2); Philosopher p3 = new Philosopher("哲学家C",c2,c1); Philosopher p4 = new Philosopher("哲学家D",c1,c4); p1.start(); p2.start(); p3.start(); p4.start(); } }
这个模式下死锁现象是多线程并发的偶然现象,我们测试一下能不能碰得到。
由于当哲学家访问一个筷子对象时,对它进行了加锁,这时他的邻桌哲学家无法拿到此筷子,而自己再拿第二个筷子的时候,此时第二个筷子又被其他哲学家锁住,此时两两都无法使用筷子,所以产生死锁。
对于此问题如何解决死锁想象呢?可以给每个哲学家使用筷子一个时间(也相当于等待筷子时间),使用完后就将筷子放下。由于处于对面的互相不影响,可以同时进行。如下:public class Philosopher extends Thread{ private String name; private Chopsticks leftChopstick; private Chopsticks rightChopstick; private long time;//增加一个等待时间 public Philosopher(String name, Chopsticks leftChopstick, Chopsticks rightChopstick,long time) { this.name = name; this.leftChopstick = leftChopstick; this.rightChopstick = rightChopstick; this.time = time; } @Override public void run() { eat(); } public void eat(){ try { Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (leftChopstick){ System.out.println(this.name + "拿起了左手边的"+leftChopstick.getNum()+"号筷子"); synchronized (rightChopstick){ System.out.println(this.name + "拿起了右手边的"+rightChopstick.getNum()+"号筷子"); System.out.println("==============================>"+this.name + "开始吃饭了!"); } } } }
再次测试:
public class TestMain { public static void main(String[] args) { Chopsticks c1 = new Chopsticks(1); Chopsticks c2 = new Chopsticks(2); Chopsticks c3 = new Chopsticks(3); Chopsticks c4 = new Chopsticks(4); Philosopher p1 = new Philosopher("哲学家A",c4,c3,0); Philosopher p2 = new Philosopher("哲学家B",c3,c2,500); Philosopher p3 = new Philosopher("哲学家C",c2,c1,0); Philosopher p4 = new Philosopher("哲学家D",c1,c4,500); p1.start(); p2.start(); p3.start(); p4.start(); } }
经过多次测试,发现可以解决死锁问题。
哲学家就餐问题-多线程并发死锁现象
最新推荐文章于 2024-04-26 20:40:14 发布