fork download
  1. /**
  2.  * Chandy/Misra solution implementation.
  3.  *
  4.  * 1. For every pair of philosophers give chopstick to the one with the lower ID.
  5.  *
  6.  * 2. Each chopstick can either be dirty or clean. Initially, all chopsticks are
  7.  * dirty.
  8.  *
  9.  * 3. When a philosopher wants to eat, he must obtain the chopsticks he does not
  10.  * have from his contending neighbors. For all such chopsticks he does not have, he
  11.  * sends a request message and waits. See Philosopher.obtainChopsticksIfNecessary()
  12.  * and Philosopher.waitForChopstick()
  13.  *
  14.  * 4. Only dirty chopstick can be given up. When the chopstick sent over, it
  15.  * gets cleaned. See Philosopher.giveUpChopstickIfNecessary()
  16.  *
  17.  * 5. After a philosopher is done eating, all his chopsticks become dirty. See
  18.  * Philosopher.eat()
  19.  *
  20.  * 6. Philosopher can eat only when both chopsticks present. Chopsticks can not
  21.  * be sent away when philosopher is eating. Chopsticks change state ONLY inside the
  22.  * owner's thread so philosopher does not need to lock them when he's eating.
  23.  *
  24.  * 7. What he needs however is to check his neighbors periodically in order to
  25.  * send them chopsticks when they're ready to eat. See processChopsticks() and
  26.  * giveUpChopstickIfNecessary()
  27.  *
  28.  * The clean/dirty labels give preference to the most "starved" processes. It
  29.  * solves the starvation problem.
  30.  *
  31.  * Initializing the system so that philosophers with lower IDs have dirty
  32.  * chopsticks AND continuous tracking neighbor's state gives a guarantee that
  33.  * deadlock cannot occur and system has overall progress.
  34.  *
  35.  */
  36.  
  37. class Program {
  38.  
  39. public static void main(String[] args) {
  40.  
  41. final int philosophersCount = 6;
  42. final int eatCount = 5;
  43.  
  44. Philosopher[] philosophers = new Philosopher[philosophersCount];
  45. Chopstick[] chopsticks = new Chopstick[philosophersCount];
  46.  
  47. for (int i = 0; i < philosophersCount; i++)
  48. chopsticks[i] = new Chopstick(i + 1);
  49.  
  50. for (int i = 0; i < philosophersCount; i++)
  51. philosophers[i] = new Philosopher(i + 1, chopsticks[i],
  52. chopsticks[(i + 1) % philosophersCount], eatCount);
  53.  
  54. // set neighbors and assign owners: give the chopsticks to the philosopher with the lower ID
  55. philosophers[0].leftNeighbor = philosophers[philosophersCount - 1];
  56. philosophers[0].rightNeighbor = philosophers[1];
  57. chopsticks[0].owner = philosophers[0];
  58. for (int i = 1; i < philosophersCount; i++) {
  59. philosophers[i].leftNeighbor = philosophers[(i - 1) % philosophersCount];
  60. philosophers[i].rightNeighbor = philosophers[(i + 1) % philosophersCount];
  61. chopsticks[i].owner = philosophers[i - 1];
  62. }
  63.  
  64. System.out.println("Dinner is starting!\n");
  65. for (int i = 0; i < philosophersCount; i++)
  66. philosophers[i].start();
  67.  
  68. // wait all threads to complete
  69. for (int i = 0; i < philosophersCount; i++)
  70. philosophers[i].join();
  71. System.out.println("Dinner is over!");
  72. }
  73. }
  74.  
  75. class Philosopher implements Runnable {
  76.  
  77. final int id;
  78. final Chopstick leftChopstick, rightChopstick;
  79. final int eatCount;
  80. Philosopher leftNeighbor, rightNeighbor;
  81.  
  82. final Thread thread;
  83.  
  84. int eatNum = 0; // total # times Philosopher has eaten
  85. int eatInRaw = 0; // how many times Philosopher has eaten in a row
  86.  
  87. boolean goingToEatRequest = false; // signal "I want to eat"
  88.  
  89. public Philosopher(int id, Chopstick leftChopstick,
  90. Chopstick rightChopstick, int eatCount) {
  91. super();
  92. this.id = id;
  93. this.leftChopstick = leftChopstick;
  94. this.rightChopstick = rightChopstick;
  95. this.eatCount = eatCount;
  96. thread = new Thread(this);
  97. }
  98.  
  99.  
  100. /**
  101.   * Main loop
  102.   */
  103. public void run() {
  104. while (eatNum < eatCount) {
  105. think();
  106. processChopsticks(true);
  107. obtainChopsticksIfNecessary();
  108. eat();
  109. processChopsticks(eatNum != eatCount); // give up chopsticks unconditionally after the last iteration
  110. }
  111. }
  112.  
  113.  
  114. void obtainChopsticksIfNecessary() {
  115. // indicate that we need chopsticks so the neighbors send them
  116. goingToEatRequest = true;
  117. waitForChopstick(leftChopstick);
  118. waitForChopstick(rightChopstick);
  119. goingToEatRequest = false;
  120. }
  121.  
  122.  
  123. /**
  124.   * Monitor "Guarded Wait" implementation
  125.   */
  126. void waitForChopstick(Chopstick chopstick) {
  127. if (chopstick.owner != this) {
  128. synchronized (chopstick) {
  129.  
  130. // System.out.format("Philosopher %d WAITING for chopstick %d.\n",
  131. // id, chopstick.id);
  132.  
  133. try {
  134. while (chopstick.owner != this) {
  135. // while waiting, Philosopher must be able to release
  136. // dirty chopstick he owns to avoid deadlock
  137. processChopsticks(true);
  138. chopstick.wait();
  139. }
  140. } catch (InterruptedException e) {
  141. System.out.println("InterruptedException caught");
  142. }
  143. }
  144. }
  145. System.out.format("Philosopher %d picks up %s chopstick.\n", id, chopstick == leftChopstick ? "left" : "right");
  146. }
  147.  
  148.  
  149. /**
  150.   * Philosopher is checking his neighbor's state periodically and releases
  151.   * chopsticks synchronously, in his thread. If isRequestRequired set to
  152.   * true philosopher can send chopstick he owns only if the neighbor requested
  153.   * it. If isRequestRequired is false he can release chopstick regardless
  154.   * of neighbor's request (useful when he stops checking neighbor's state).
  155.   */
  156. void processChopsticks(boolean isRequestRequired) {
  157. giveUpChopstickIfNecessary(leftChopstick, leftNeighbor, isRequestRequired);
  158. giveUpChopstickIfNecessary(rightChopstick, rightNeighbor, isRequestRequired);
  159. }
  160.  
  161.  
  162. /**
  163.   * Philosopher gives up only dirty chopstick he owns,
  164.   * on request OR unconditionally (e.g. if he's finished dinner
  165.   * and not going to track his neighbor's requests anymore)
  166.   */
  167. void giveUpChopstickIfNecessary(Chopstick chopstick, Philosopher receiver, boolean isRequestRequired) {
  168.  
  169. synchronized (chopstick) {
  170. if ( (receiver.goingToEatRequest || !isRequestRequired) && // give up chopstick only on request OR unconditionally
  171. !chopstick.isClean && // only dirty chopstick
  172. chopstick.owner == this) { // only chopstick he owns
  173. chopstick.isClean = true; // wash chopstick before sending out
  174. chopstick.owner = receiver;
  175. eatInRaw = 0; // reset # eats-in-raw because chopstick sent out
  176.  
  177. // System.out.format("Chopstick %d sent to Philosopher %d by Philosopher %d\n", chopstick.id,
  178. // chopstick.owner.id, id);
  179.  
  180. chopstick.notify(); // notify waiting threads
  181. }
  182. }
  183. }
  184.  
  185.  
  186. void eat() {
  187. eatInRaw++;
  188. eatNum++;
  189. rightChopstick.isClean = leftChopstick.isClean = false;
  190. String eatersList = eaters.addEater(this);
  191. System.out.format("Philosopher %d starts eating. Eats in raw: %d. Eating at present: %s.\n",
  192. id, eatInRaw, eatersList);
  193. // System.out.format("Philosopher %d eats.\n", id);
  194. StaticMethods.sleep(StaticMethods.random(100, 200));
  195. eaters.removeEater(this);
  196. // System.out.format("Philosopher %d finished eating (%d times).\n", id, eatNum);
  197. System.out.format("Philosopher %d puts down right chopstick.\n", id);
  198. System.out.format("Philosopher %d puts down left chopstick.\n", id);
  199. }
  200.  
  201.  
  202. void think() {
  203. // System.out.format("Philosopher %d thinks.\n", id);
  204. StaticMethods.sleep(StaticMethods.random(100, 200));
  205. }
  206.  
  207.  
  208. public void start() {
  209. thread.start();
  210. }
  211.  
  212.  
  213. public void join() {
  214. try {
  215. thread.join();
  216. } catch (InterruptedException e) {
  217. System.out.println("InterruptedException caught");
  218. }
  219. }
  220.  
  221. }
  222.  
  223. class Chopstick {
  224.  
  225. final int id;
  226. volatile Philosopher owner;
  227. volatile boolean isClean = false;
  228.  
  229. public Chopstick(int id) {
  230. super();
  231. this.id = id;
  232. }
  233. }
  234.  
  235. /**
  236.  * Auxiliary static methods.
  237.  *
  238.  */
  239. class StaticMethods {
  240.  
  241. /**
  242.   * Generates random integer [Min, Max]
  243.   */
  244. public static int random(int Min, int Max) {
  245. return Min + (int) (Math.random() * ((Max - Min) + 1));
  246. }
  247.  
  248. /**
  249.   * Sleeps delay ms
  250.   */
  251. public static void sleep(int delay)
  252. {
  253. try {
  254. Thread.sleep(delay);
  255. } catch (InterruptedException e) {
  256. System.out.println("InterruptedException caught");
  257. }
  258. }
  259. }
  260.  
  261. /**
  262.  * Auxiliary class. Tracks persons eating at present
  263.  *
  264.  */
  265. class eaters {
  266.  
  267. static java.util.List<Philosopher> eaters = new java.util.ArrayList<Philosopher>();
  268.  
  269. public synchronized static String addEater(Philosopher philosopher) {
  270. eaters.add(philosopher);
  271. return eatersToString();
  272. }
  273.  
  274. public synchronized static String removeEater(Philosopher philosopher) {
  275. eaters.remove(philosopher);
  276. return eatersToString();
  277. }
  278.  
  279. private static String eatersToString() {
  280. String s = "";
  281. for (Philosopher philosopher : eaters)
  282. s += philosopher.id + " ";
  283. return s.trim();
  284. }
  285. }
  286.  
Success #stdin #stdout 0.19s 74224KB
stdin
Standard input is empty
stdout
Dinner is starting!

Philosopher 6 picks up left chopstick.
Philosopher 4 picks up left chopstick.
Philosopher 4 picks up right chopstick.
Philosopher 6 picks up right chopstick.
Philosopher 2 picks up left chopstick.
Philosopher 2 picks up right chopstick.
Philosopher 4 starts eating. Eats in raw: 1. Eating at present: 4.
Philosopher 6 starts eating. Eats in raw: 1. Eating at present: 4 2 6.
Philosopher 2 starts eating. Eats in raw: 1. Eating at present: 4 2.
Philosopher 2 puts down right chopstick.
Philosopher 2 puts down left chopstick.
Philosopher 3 picks up left chopstick.
Philosopher 4 puts down right chopstick.
Philosopher 4 puts down left chopstick.
Philosopher 3 picks up right chopstick.
Philosopher 5 picks up left chopstick.
Philosopher 3 starts eating. Eats in raw: 1. Eating at present: 6 3.
Philosopher 6 puts down right chopstick.
Philosopher 6 puts down left chopstick.
Philosopher 5 picks up right chopstick.
Philosopher 5 starts eating. Eats in raw: 1. Eating at present: 3 5.
Philosopher 1 picks up left chopstick.
Philosopher 1 picks up right chopstick.
Philosopher 1 starts eating. Eats in raw: 1. Eating at present: 3 5 1.
Philosopher 3 puts down right chopstick.
Philosopher 3 puts down left chopstick.
Philosopher 1 puts down right chopstick.
Philosopher 1 puts down left chopstick.
Philosopher 2 picks up left chopstick.
Philosopher 2 picks up right chopstick.
Philosopher 2 starts eating. Eats in raw: 1. Eating at present: 5 2.
Philosopher 5 puts down right chopstick.
Philosopher 5 puts down left chopstick.
Philosopher 6 picks up left chopstick.
Philosopher 6 picks up right chopstick.
Philosopher 6 starts eating. Eats in raw: 1. Eating at present: 2 6.
Philosopher 2 puts down right chopstick.
Philosopher 2 puts down left chopstick.
Philosopher 6 puts down right chopstick.
Philosopher 6 puts down left chopstick.
Philosopher 1 picks up left chopstick.
Philosopher 1 picks up right chopstick.
Philosopher 1 starts eating. Eats in raw: 1. Eating at present: 1.
Philosopher 4 picks up left chopstick.
Philosopher 4 picks up right chopstick.
Philosopher 4 starts eating. Eats in raw: 1. Eating at present: 1 4.
Philosopher 3 picks up left chopstick.
Philosopher 4 puts down right chopstick.
Philosopher 4 puts down left chopstick.
Philosopher 3 picks up right chopstick.
Philosopher 3 starts eating. Eats in raw: 1. Eating at present: 1 3.
Philosopher 5 picks up left chopstick.
Philosopher 5 picks up right chopstick.
Philosopher 5 starts eating. Eats in raw: 1. Eating at present: 1 3 5.
Philosopher 1 puts down right chopstick.
Philosopher 1 puts down left chopstick.
Philosopher 2 picks up left chopstick.
Philosopher 5 puts down right chopstick.
Philosopher 5 puts down left chopstick.
Philosopher 6 picks up left chopstick.
Philosopher 6 picks up right chopstick.
Philosopher 6 starts eating. Eats in raw: 1. Eating at present: 3 6.
Philosopher 3 puts down right chopstick.
Philosopher 3 puts down left chopstick.
Philosopher 2 picks up right chopstick.
Philosopher 2 starts eating. Eats in raw: 1. Eating at present: 6 2.
Philosopher 4 picks up left chopstick.
Philosopher 4 picks up right chopstick.
Philosopher 4 starts eating. Eats in raw: 1. Eating at present: 6 2 4.
Philosopher 6 puts down right chopstick.
Philosopher 6 puts down left chopstick.
Philosopher 1 picks up left chopstick.
Philosopher 2 puts down right chopstick.
Philosopher 2 puts down left chopstick.
Philosopher 1 picks up right chopstick.
Philosopher 1 starts eating. Eats in raw: 1. Eating at present: 4 1.
Philosopher 4 puts down right chopstick.
Philosopher 4 puts down left chopstick.
Philosopher 5 picks up left chopstick.
Philosopher 5 picks up right chopstick.
Philosopher 5 starts eating. Eats in raw: 1. Eating at present: 1 5.
Philosopher 3 picks up left chopstick.
Philosopher 3 picks up right chopstick.
Philosopher 3 starts eating. Eats in raw: 1. Eating at present: 1 5 3.
Philosopher 1 puts down right chopstick.
Philosopher 1 puts down left chopstick.
Philosopher 2 picks up left chopstick.
Philosopher 5 puts down right chopstick.
Philosopher 5 puts down left chopstick.
Philosopher 6 picks up left chopstick.
Philosopher 6 picks up right chopstick.
Philosopher 6 starts eating. Eats in raw: 1. Eating at present: 3 6.
Philosopher 3 puts down right chopstick.
Philosopher 3 puts down left chopstick.
Philosopher 2 picks up right chopstick.
Philosopher 4 picks up left chopstick.
Philosopher 2 starts eating. Eats in raw: 1. Eating at present: 6 2.
Philosopher 6 puts down right chopstick.
Philosopher 6 puts down left chopstick.
Philosopher 1 picks up left chopstick.
Philosopher 4 picks up right chopstick.
Philosopher 4 starts eating. Eats in raw: 1. Eating at present: 2 4.
Philosopher 2 puts down right chopstick.
Philosopher 2 puts down left chopstick.
Philosopher 1 picks up right chopstick.
Philosopher 1 starts eating. Eats in raw: 1. Eating at present: 4 1.
Philosopher 3 picks up left chopstick.
Philosopher 1 puts down right chopstick.
Philosopher 1 puts down left chopstick.
Philosopher 4 puts down right chopstick.
Philosopher 4 puts down left chopstick.
Philosopher 3 picks up right chopstick.
Philosopher 3 starts eating. Eats in raw: 1. Eating at present: 3.
Philosopher 5 picks up left chopstick.
Philosopher 5 picks up right chopstick.
Philosopher 5 starts eating. Eats in raw: 1. Eating at present: 3 5.
Philosopher 3 puts down right chopstick.
Philosopher 3 puts down left chopstick.
Philosopher 4 picks up left chopstick.
Philosopher 2 picks up left chopstick.
Philosopher 2 picks up right chopstick.
Philosopher 2 starts eating. Eats in raw: 1. Eating at present: 5 2.
Philosopher 5 puts down right chopstick.
Philosopher 5 puts down left chopstick.
Philosopher 4 picks up right chopstick.
Philosopher 4 starts eating. Eats in raw: 1. Eating at present: 2 4.
Philosopher 6 picks up left chopstick.
Philosopher 6 picks up right chopstick.
Philosopher 6 starts eating. Eats in raw: 1. Eating at present: 2 4 6.
Philosopher 2 puts down right chopstick.
Philosopher 2 puts down left chopstick.
Philosopher 3 picks up left chopstick.
Philosopher 4 puts down right chopstick.
Philosopher 4 puts down left chopstick.
Philosopher 5 picks up left chopstick.
Philosopher 3 picks up right chopstick.
Philosopher 3 starts eating. Eats in raw: 1. Eating at present: 6 3.
Philosopher 6 puts down right chopstick.
Philosopher 6 puts down left chopstick.
Philosopher 5 picks up right chopstick.
Philosopher 5 starts eating. Eats in raw: 1. Eating at present: 3 5.
Philosopher 1 picks up left chopstick.
Philosopher 1 picks up right chopstick.
Philosopher 1 starts eating. Eats in raw: 1. Eating at present: 3 5 1.
Philosopher 3 puts down right chopstick.
Philosopher 3 puts down left chopstick.
Philosopher 1 puts down right chopstick.
Philosopher 1 puts down left chopstick.
Philosopher 5 puts down right chopstick.
Philosopher 5 puts down left chopstick.
Dinner is over!