/** * Dining Philosophers * @author David Von Leon (11120) * * Team: Tiziano Munaro (11131), David Von Leon (11120) * * Philosophers can only eat whenever they acquired the chopstick * on their right and the one on their left. Whenever there is only one * chopstick available it has to be released immediately to * prevent deadlocks. And since each philosopher can only eat for * a certain, random amount of time before their chopstick will be * released again, starvation is prevented as well. * * The synchronized block prevents different threads (philosophers) to * execute the inner code at the same time. Therefore only one thread * can try to acquire two chopsticks next to it. This avoids lifelocks as well, * since only one philosopher at a time is allowed to acquire chopsticks. * */ import java.util.concurrent.Semaphore; class DiningPhilosophers { public static void main(String[] args) { int size = 5; int duration = 60; // initialize chopsticks Chopstick[] cs = new Chopstick[size]; for (int i = 0; i < size; i++) cs[i] = new Chopstick(); // initialize philosophers Philosopher[] ph = new Philosopher[size]; for (int i = 0; i < size; i++) { ph[i] = new Philosopher(i, cs[i], cs[(i + 1) % size]); ph[i].start(); } // run try { Thread.sleep(duration * 1000); } catch (InterruptedException ie) { } // stop philosophers for (int i = 0; i < size; i++) ph[i].stopIt(); // report for (int i = 0; i < size; i++) ph[i].report(); } } // Chopstick class class Chopstick { private Semaphore s; public Chopstick() { s = new Semaphore(1); } public void acquire() { try { s.acquire(); } catch (InterruptedException ie) { } } public void release() { s.release(); } } // Philosopher Class class Philosopher extends Thread { public Chopstick lt, rt; private String name; private boolean run; private int meals, etime; private static Object lock; public Philosopher(int id, Chopstick cone, Chopstick ctwo) { name = "Philosopher " + id; lt = cone; rt = ctwo; meals = etime = 0; run = true; lock = new Object(); } public void run() { while (run) { System.out.println(name + " is thinking."); int rnds = randomSleep(); if (!run) break; synchronized (lock) { lt.acquire(); rt.acquire(); } System.out.println(name + " is eating."); etime += rnds; meals++; lt.release(); rt.release(); } } public void stopIt() { run = false; } public void report() { System.out.println(name + " had " + meals + " meals in " + etime + " ms."); } private int randomSleep() { int rnds = (int) (Math.random() * 1000); try { Thread.sleep(rnds); } catch (InterruptedException ie) { } return rnds; } }