Distributed memory dining philosophers decentralized algorithm, message passing phil haveL dirtyL haveR dirtyR 1 T f T f 2 f f T f 3 f f T f 4 f f T f 5 f f f f if not assymetric initial configuration, then deadlock if all get hungry at same time (get stuck in while (!(haveL && haveR)) { .... } since no forks are dirty) class ServantCondition implements Condition {... private boolean hungry = false; private boolean dirtyL = false, dirtyR = false; ... public boolean checkCondition(Object m) { if (m instanceof Hungry) return true; else if (!hungry) return true; else if (m instanceof PassL || m instanceof PassR) return true; else if (m instanceof NeedL && dirtyL) return true; else if (m instanceof NeedR && dirtyR) return true; else return false; } } class Servant implements Runnable {... private BinarySemaphore eat = new BinarySemaphore(0); private BinarySemaphore releaseForks = new BinarySemaphore(0); ... public void takeForks(int id) { myChannel.send(new Hungry()); P(eat); } public void putForks(int id) { V(releaseForks); } public void run() { // servant thread Object message = null; ServantCondition sc = null; boolean hungry = false; while (true) { sc = new ServantCondition(hungry, dirtyL, dirtyR); message = myChannel.receive(sc); if (message instanceof Hungry) { hungry = true; if (!haveR) rightServantChannel.send(new NeedL()); if (!haveL) leftServantChannel.send(new NeedR()); while (!(haveR && haveL)) { sc = new ServantCondition(hungry, dirtyL, dirtyR); message = myChannel.receive(sc); if (message instanceof PassL) { haveL = true; dirtyL = false; } else if (message instanceof PassR) { // right servant sends fork haveR = true; dirtyR = false; } else if (message instanceof NeedL) { haveL = false; dirtyL = false; leftServantChannel.send(new PassR()); leftServantChannel.send(new NeedR()); } else if (message instanceof NeedR) { haveR = false; dirtyR = false; rightServantChannel.send(new PassL()); rightServantChannel.send(new NeedL()); } } V(eat); dirtyR = true; dirtyL = true; P(releaseForks); hungry = false; } else if (message instanceof NeedR) { haveR = false; dirtyR = false; rightServantChannel.send(new PassL()); } else if (message instanceof NeedL) { haveL = false; dirtyL = false; leftServantChannel.send(new PassR()); } } } } the above can deadlock if we don't ask for a dirty fork back that we had to release if we release a fork whether or not it is dirty (and ask for it back) then forks can oscillate back and forth endlessly QUESTION??? given the initial configuration, doesn't the following sequence of events lead to deadlock? initial configuration: no forks dirty, phil 1 has both forks, phil 2 thru 4 have right fork but not left, phil 5 has neither, all phils thinking phil 5 get H, asks for its R fork from phil 1, gets it, asks phil 4 for L fork, while that message is in transit.... phil 4 gets H, has R fork, asks phil 3 for L fork, while that message is in transit...... phil 3 gets H, has R fork, asks phil 2 for L fork, while that message is in transit...... phil 2 gets H, has R fork, asks phil 1 for L fork, while that message is in transit...... phil 1 gets H, has R fork, asks phil 5 for L fork that it gave up now all the messages arrive, all phils are hungry, each holding a clean fork (its right one) and asking for its left fork isn't this deadlock? is a solution to this to make both forks given to phil 1 in the beginning (artificially) dirty? YES! Change philosopher 1 to the following in the table above to prevent deadlock. phil haveL dirtyL haveR dirtyR 1 T T T T But this still shows that we do not have maximal parallelism, i.e. we don't have deadlock, but we do have a chain of hungry philosophers, none eating when one could be. Now there is no deadlock because from the above initial state we can never get to a state in which every servant holds one clean fork and wants a second (p. 459 of Andrews' "Concurrent Programming"). somebody just ate last and has two dirty forks so now we are back to something like the initial configuration a hold-and-wait cycle can't form either clockwise or counterclockwise if one starts to form clockwise, then the philosopher who just fininshed eating's right fork will go right and its right neighbor can eat