This is an animation of the ``distributed'' dining philosophers. There is no central server algorithm allocating the forks based on global knowledge of the states of the philosophers. Each fork moves back and forth between the two philosophers on either side of it as the philosophers eat with the fork. The two philosophers send messages back and forth to coordinate their use of the fork between them. A clean fork is represented with a gray line. A fork is yellow when currently being used by a philosopher to eat. When a philosopher finishes eating, its two forks turn orange. When a philosopher passes a fork to its neighbor, the fork changes to gray. In order to prevent starvation, a philosopher is required to relinquish a dirty fork, one it last used to eat, to a hungry neighbor.
public void takeForks(int id) { xa.color("phil"+id, Color.green); // animation xa.fill("phil"+id, xa.SOLID); // animation myChannel.send(new Hungry()); // non blocking P(eat); // wait for empty message xa.color("phil"+id, Color.blue); // animation xa.fill("phil"+id, xa.SOLID); // animation } public void putForks(int id) { xa.fill("phil"+id, xa.OUTLINE); // animation xa.color("phil"+id, Color.black); // animation V(releaseForks); // send empty message } public void run() { ... 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)) { // while hungry, wait for forks sc = new ServantCondition(hungry, dirtyL, dirtyR); message = myChannel.receive(sc); if (message instanceof PassL) { // left servant sends fork // Move the fork from where it was to be next to this philosopher and then // change its symbol to be light gray, i.e., not dirty. xa.moveTo(forkL, holderL); xa.color(forkL, Color.lightGray); xa.fill("phil"+id, xa.HALF); haveL = true; dirtyL = false; } else if (message instanceof PassR) { // right servant sends fork // Ditto. xa.moveTo(forkR, holderR); xa.color(forkR, Color.lightGray); xa.fill("phil"+id, xa.HALF); haveR = true; dirtyR = false; } else if (message instanceof NeedL) { // dirtyL is true // hungry philosopher must relinquish dirty fork // to avoid starvation haveL = false; dirtyL = false; leftServantChannel.send(new PassR()); leftServantChannel.send(new NeedR()); xa.color("phil"+id, Color.red); } else if (message instanceof NeedR) { // dirtyR is true // hungry philosopher must relinquish dirty fork // to avoid starvation haveR = false; dirtyR = false; rightServantChannel.send(new PassL()); rightServantChannel.send(new NeedL()); xa.color("phil"+id, Color.red); } V(eat); dirtyR = true; dirtyL = true; // Now that the philosopher is eating, its forks are getting dirty so // change their symbols to be yellow. xa.color(forkL, Color.yellow); xa.color(forkR, Color.yellow); P(releaseForks); hungry = false; // Now that the philosopher has finished eating, its forks are dirty so // change their symbols to be orange. xa.color(forkL, Color.orange); xa.color(forkR, Color.orange); } else if (message instanceof NeedR) { // not hungry and have right fork haveR = false; dirtyR = false; rightServantChannel.send(new PassL()); } else if (message instanceof NeedL) { // not hungry and have left fork haveL = false; dirtyL = false; leftServantChannel.send(new PassR()); } }At the bottom of the animation window is a button and text field showing the default values of some of the command line arguments. Alter these as needed and click the button.
-p: number of philosophers
-R: number of seconds to run
© 1998 Stephen J. Hartley