// : c13:diningphilosophers.java // demonstrates how deadlock can be hidden in a program. // {args: 5 0 deadlock 4} // from 'thinking in java, 3rd ed.' (c) bruce eckel 2002 // www.bruceeckel.com. see copyright notice in copyright.txt.
import java.util.random; import java.util.timer; import java.util.timertask;
class chopstick { private static int counter = 0;
private int number = counter++;
public string tostring() { return "chopstick " + number; } }
class philosopher extends thread { private static random rand = new random();
private static int counter = 0;
private int number = counter++;
private chopstick leftchopstick;
private chopstick rightchopstick;
static int ponder = 0; // package access
public philosopher(chopstick left, chopstick right) { leftchopstick = left; rightchopstick = right; start(); }
public void think() { system.out.println(this + " thinking"); if (ponder > 0) try { sleep(rand.nextint(ponder)); } catch (interruptedexception e) { throw new runtimeexception(e); } }
public void eat() { synchronized (leftchopstick) { system.out.println(this + " has " + this.leftchopstick + " waiting for " + this.rightchopstick); synchronized (rightchopstick) { system.out.println(this + " eating"); } } }
public string tostring() { return "philosopher " + number; }
public void run() { while (true) { think(); eat(); } } }
public class diningphilosophers { public static void main(string[] args) { if (args.length < 3) { system.err.println("usage:/n" + "java diningphilosophers numberofphilosophers " + "ponderfactor deadlock timeout/n" + "a nonzero ponderfactor will generate a random " + "sleep time during think()./n" + "if deadlock is not the string " + "'deadlock', the program will not deadlock./n" + "a nonzero timeout will stop the program after " + "that number of seconds."); system.exit(1); } philosopher[] philosopher = new philosopher[integer.parseint(args[0])]; philosopher.ponder = integer.parseint(args[1]); chopstick left = new chopstick(), right = new chopstick(), first = left; int i = 0; while (i < philosopher.length - 1) { philosopher[i++] = new philosopher(left, right); left = right; right = new chopstick(); } if (args[2].equals("deadlock")) philosopher[i] = new philosopher(left, first); else // swapping values prevents deadlock: philosopher[i] = new philosopher(first, left); // optionally break out of program: if (args.length >= 4) { int delay = integer.parseint(args[3]); if (delay != 0) new timeout(delay * 1000, "timed out"); } } } ///:~
class timeout extends timer { public timeout(int delay, final string msg) { super(true); // daemon thread schedule(new timertask() { public void run() { system.out.println(msg); system.exit(0); } }, delay); } } ///:~ |