我已经实现了餐饮哲学家问题的资源层次解决方案。当我尝试比较两个筷子的n值时,它们最终陷入僵局。但是,如果我使用其hashCodes而不是n值,则它将运行平稳。为什么会有这种差异?他们不是一天结束时都数字吗?import java.util.Random;class Chopstick { public final int n; public Chopstick(int n) { this.n = n; }}class Philosopher extends Thread { private Chopstick left, right; private Random random; private final int n; public Philosopher(int n, Chopstick left, Chopstick right) { this.n = n; if (left.n > right.n) { // no deadlock if I replace this with left.hashCode() > right.hashCode() this.right = left; this.left = right; } else { this.left = left; this.right = right; } this.random = new Random(); } @Override public void run() { try { while (true) { Thread.sleep(random.nextInt(10)); // Think synchronized(left) { synchronized(right) { System.out.println("P " + n + " eating"); Thread.sleep(random.nextInt(10)); } } } } catch(InterruptedException ie) { ie.printStackTrace(); } }}class Main { public static void main(String[] args) { final int n = 3; Chopstick[] sticks = new Chopstick[n]; Philosopher[] ps = new Philosopher[n]; for (int i = 0; i < n; i++) { sticks[i] = new Chopstick(n); } for (int i = 0; i < n; i++) { ps[i] = new Philosopher(i, sticks[i], sticks[(i + 1) % n]); ps[i].start(); } }} 最佳答案 您的问题与以下事实有关:您不管理left.n == right.n的情况,不幸的是,您没有使用Chopstick初始化sticks[i] = new Chopstick(i)数组,而是使用了sticks[i] = new Chopstick(n),这样您只有left.n == right.n类型的情况管理不善,您将陷入僵局。由于您没有覆盖方法hashCode(),因此使用hashCode()可以避免该问题,因为它们是Chopstick的不同实例,且具有不同的hashCode()值,但是您仍然可以遇到我们有两个不同的与相同的Chopstick。因此,您仍然必须管理价值相等的情况。正确管理相等值的方法是使用第三个锁,称为“平分”锁class Philosopher extends Thread { // The tie breaking lock private static Object tieLock = new Object(); ... private void printAndSleep() throws InterruptedException { synchronized(left) { synchronized(right) { System.out.println("P " + n + " eating"); Thread.sleep(random.nextInt(10)); } } } public void run() { ... if (left.n == right.n) { // Equal values so we need first to acquire the tie breaking lock synchronized (tieLock) { printAndSleep(); } } else { printAndSleep(); } ... }}管理锁排序的一种更通用的方法是依靠hashCode()作为每个实例的值进行排序,而不是使用字段的值或System.identityHashCode(obj),因为这种方式您将不必依赖于目标对象类型的特定内容。第10.1.2节Java Concurrency in Practice中的Brian Goetz动态锁定顺序死锁中有更多详细信息
07-26 01:57