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. To start the animation, push the ``Start'' button after checking the command line arguments text field and clicking that button. An applet appears here if you have a Java-enabled browser.


© 1998 Stephen J. Hartley