Java 餐饮哲学家与协调员陷入僵局

Java Dining Philosophers Dead Lock with Koordinator

我有哲学家就餐问题。我想用 Monitor 来解决它。 Monitor 协调左右分叉的访问。 Monitor 使用 Array fork 表示每个 Philosoph 的分叉数量。

如果哲学家 i 可以的话 (fork[i] == 2) 他会拿他邻居的一把叉子。如果他放叉子,条目将再次增加。

这是我的哲学家代码:

public class Philosoph {

    protected volatile boolean isRunning = true;

    protected final int id;
    protected final Fork leftFork;
    protected final Fork rightFork;
    protected int eatCounter;

    public Philosoph(int id, Fork leftFork, Fork rightFork) {
        this.id = id;
        this.leftFork = leftFork;
        this.rightFork = rightFork;
        eatCounter = 0;
    }

    public void eat() throws InterruptedException {
        eatCounter++;
        TimeUnit.MILLISECONDS.sleep(10);
    }

    public void think() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(5);
    }

    public void stop() {
        isRunning = false;
    } 
}
public class KoordinierterPhilosph extends Philosoph implements Callable<Integer> {

    Koordinator kord;

    public KoordinierterPhilosph(Koordinator kord, int id, Fork leftFork, Fork rightFork) {
        super(id, leftFork, rightFork);
        this.kord = kord;
    }

    @Override
    public Integer call() throws Exception {
        while (isRunning) {
            try {
                think();
                kord.takeFork(id);
                eat();
                kord.releaseFork(id);
            } catch (InterruptedException ex) {
                break;
            }
        }
        return eatCounter;
    }
}

这是我的显示器Class:

public class Koordinator {

    private int[] forks;
    private int anzahlPhilosophen;
    private ReentrantLock lock = new ReentrantLock();
    private Condition[] readyToEatCondition;

    public Koordinator(int anzahlPhilosophen) {
        this.anzahlPhilosophen = anzahlPhilosophen;
        forks = new int[anzahlPhilosophen];
        readyToEatCondition = new Condition[anzahlPhilosophen];
        for (int i = 0; i < anzahlPhilosophen; i++) {
            forks[i] = 2;
            readyToEatCondition[i] = lock.newCondition();
        }
    }

    public void takeFork(int id) throws InterruptedException {
        while (forks[id] != 2) {
            readyToEatCondition[id].await();
        }
        forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] - 1;
        if (id - 1 == -1) {
            id = anzahlPhilosophen - 1;
        } else {
            id = id - 1;
        }
        forks[id] = forks[id] - 1;
    }

    public void releaseFork(int id) {
        int idNew = 0;
        forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] + 1;
        if (id - 1 == -1) {
            idNew = anzahlPhilosophen - 1;
        } else {
            idNew = id - 1;
        }
        forks[idNew] = forks[idNew] + 1;

        if (forks[(id + 1) % anzahlPhilosophen] == 2) {
            readyToEatCondition[(id + 1) % anzahlPhilosophen].signal();
        }
        if (forks[idNew] == 2) {
            readyToEatCondition[idNew].signal();
        }
    }
}

这是我的主要例程:

    public class Runner {

    private static ExecutorService threadPool;
    private static int gesamt = 0;

    public static void main(String[] args) {
        ExecutorService serv = Executors.newCachedThreadPool();
        try {
            dining(5, serv);
        } catch (InterruptedException | ExecutionException ex) {
            Logger.getLogger(Ue7.DiningPhilosopher.Alg3.Runner.class.getName()).log(Level.SEVERE, null, ex);
        }
        serv.shutdown();
    }

    public static void dining(int anzahlPhilosopher, ExecutorService pool) throws InterruptedException, ExecutionException {
        threadPool = pool;
        Map<String, Future<Integer>> result = new HashMap<>();
        KoordinierterPhilosph[] philosopher = new KoordinierterPhilosph[anzahlPhilosopher];
        Koordinator kord = new Koordinator(anzahlPhilosopher);

        for (int i = 0; i < anzahlPhilosopher; i++) {
            philosopher[i] = new KoordinierterPhilosph(kord, i, null, null);

        }
        for (int i = 0; i < anzahlPhilosopher; i++) {
            result.put("Philosoph " + i, threadPool.submit(philosopher[i]));
        }

        TimeUnit.SECONDS.sleep(10);
        for (KoordinierterPhilosph p : philosopher) {
            p.stop();
        }
        for (Map.Entry pair : result.entrySet()) {
            Future<Integer> f = (Future<Integer>) pair.getValue();
            int eatPro = f.get();
            gesamt += eatPro;
            System.out.println(pair.getKey() + " " + eatPro);
        }
        System.out.println("Gesamt: " + gesamt);
    }
}

但我总是遇到死锁,但现在不知道为什么

我找到问题了。我需要在Monitor的Methods开头做一个lock。有了它我就成了 Illegal State Exception.

监视器现在看起来像这样:

public class Koordinator {

    private int[] forks;
    private int anzahlPhilosophen;
    private ReentrantLock lock = new ReentrantLock();
    private Condition[] readyToEatCondition;

    public Koordinator(int anzahlPhilosophen) {
        this.anzahlPhilosophen = anzahlPhilosophen;
        forks = new int[anzahlPhilosophen];
        readyToEatCondition = new Condition[anzahlPhilosophen];
        for (int i = 0; i < anzahlPhilosophen; i++) {
            forks[i] = 2;
            readyToEatCondition[i] = lock.newCondition();
        }
    }

    public void takeForks(int id) throws InterruptedException {
       this.lock.lock();
       try {
            while (forks[id] != 2) {
                 readyToEatCondition[id].await();
            }
            forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] - 1;
            forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] = forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] - 1;
        } finally {
            this.lock.unlock();
        }
    }

    public void releaseForks(int id) {
        this.lock.lock();
        try {
            forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] + 1;
            forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] = forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] + 1;

            if (forks[(id + 1) % anzahlPhilosophen] == 2) {
                readyToEatCondition[(id + 1) % anzahlPhilosophen].signalAll();
            }
            if (forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] == 2) {
                readyToEatCondition[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen].signalAll();
            }
        } finally {
            this.lock.unlock();
        }
    }
}