哲学家就餐问题–看完不会你打我
以synchronized为例演示都吃不上饭
-
定义筷子类
class Chopstic { private final String name; public String getName() { return name; } public Chopstic(String name) { this.name = name; } }
-
定义哲学家类
class Philosophe extends Thread { private final Chopstic left; private final Chopstic right; public Philosophe(String name, Chopstic left, Chopstic right) { super(name); this.left = left; this.right = right; } @Override public void run() { while (true) { synchronized (left) { synchronized (right) { System.out.println(getName() + " 拿起了 " + left.getName() + " 和 " + right.getName()+" 筷子 开始吃饭"); } } } } }
-
测试
public static void main(String[] args) { Chopstic c1 = new Chopstic("1"); Chopstic c2 = new Chopstic("2"); Chopstic c3 = new Chopstic("3"); Chopstic c4 = new Chopstic("4"); Chopstic c5 = new Chopstic("5"); new Philosophe("苏格拉底", c1, c2).start(); new Philosophe("柏拉图", c2, c3).start(); new Philosophe("亚里士多德", c3, c4).start(); new Philosophe("赫拉克利特", c4, c5).start(); new Philosophe("阿基米德", c5, c1).start(); }
使用jconsole检测死锁,发现死锁
苏格拉底等待柏拉图,柏拉图等待亚里士多德 ,。。。。
正确解答
解决思路就是:无论已经有几个筷子了,一旦当前的筷子获取不到,不等待,直接放弃,把筷子全部释放,重新获取筷子
ReentrantLock的API正合适
-
定义筷子类 (继承ReentrantLock)
class Chopstick extends ReentrantLock { private final String name; public String getName() { return name; } public Chopstick(String name) { this.name = name; } }
-
定义哲学家类
例如:左手的筷子已经拿到了,去拿右手的筷子时失败了,if条件不成立,程序继续运行,执行finally块,解锁左手的筷子。
class Philosopher extends Thread { private final Chopstick left; private final Chopstick right; public Philosopher(String name, Chopstick left, Chopstick right) { super(name); this.left = left; this.right = right; } @Override public void run() { while (true) { if (left.tryLock()) { try { if (right.tryLock()) { try { System.out.println(Thread.currentThread().getName()+" \n左手:"+this.left.getName()+" 右手:"+right.getName() + " is eating."); } finally { right.unlock(); } } } finally { left.unlock(); } } } } }
-
测试
public static void main(String[] args) { Chopstick c1 = new Chopstick("1"); Chopstick c2 = new Chopstick("2"); Chopstick c3 = new Chopstick("3"); Chopstick c4 = new Chopstick("4"); Chopstick c5 = new Chopstick("5"); new Philosopher("苏格拉底", c1, c2).start(); new Philosopher("柏拉图", c2, c3).start(); new Philosopher("亚里士多德", c3, c4).start(); new Philosopher("赫拉克利特", c4, c5).start(); new Philosopher("阿基米德", c5, c1).start(); }
没有发现死锁