/** * * This solution is a Silberschatz Operating System book adaptation * Simulates a "monitor" using a Java class * use a lock to control access to monitor methods * **/ import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.Condition; /** * Emulates the Dining Philosophers problem */ public class DiningPh { final ReentrantLock monitor = new ReentrantLock(); // Restricts access to each public method in this class (monitor) final Condition[] self = new Condition[5]; // Access control to chopstick public enum State { Thinking, Hungry, Eating } // Philosopher's states private State[] state; // Each of the philosophers state /** * Initializes all monitor variables **/ public DiningPh() { state = new State[ 5 ]; for ( int person = 0; person < 5; person++ ) { state[ person ] = State.Thinking; self[ person ] = monitor.newCondition(); // Creates a new condition variable associated with monitor lock } } /* * Check if a philosopher can pick up his two chopsticks, if not the thread will wait * @param who philosopher number trying to pickup chopsticks */ public void pickup( int who ) { state[ who ] = State.Hungry; monitor.lock(); try { printstr( who, "will try to pickup sticks" ); test( who ); if ( state[ who ] == State.Hungry ) { printstr( who, "\tsticks are busy, will wait for them " ); self[ who ].await(); // Chopsticks are busy, thread must wait } } catch ( InterruptedException intException ) { } finally { monitor.unlock(); } printstr( who, "will start eating" ); } /* * When a philosopher ends eating, he will return chopsticks * With this two freed chopsticks, the thread need to check if one of their neighbors are waiting for one * and awake it using the test method * @param who philosopher number who returns its chopsticks */ public void putdown( int who ) { monitor.lock(); try { printstr( who, "end eating, will putdown sticks" ); state[ who ] = State.Thinking; // Change state to thinking test( (who + 4) % 5 ); // Check for right neighbor test( (who + 1) % 5 ); // Check for left heighbor } finally { monitor.unlock(); } } /* * Check if a philosopher can eat, verify if both chopsticks are free and self state to "Hungry" * @param who philosopher number checking it he can eat */ private void test( int who ) { if ( ( state[ (who + 4) % 5 ] != State.Eating ) && ( state[ who ] == State.Hungry ) && ( state[ (who + 1) % 5] != State.Eating ) ) { state[ who ] = State.Eating; printstr( who, "will signal condition" ); self[ who ].signal(); } } /* * Print each person status, called from within a thread * @param who philosopher number who want to print */ public void print( int who ) { for ( int person = 0; person < 5; person++ ) { System.out.printf( "(%d) Philosopher %d is %s \n", who, person + 1, (state[person]==State.Hungry)?"Hungry":(state[person]==State.Thinking)?"Thinking":"Eating"); } } /* * */ public void printstr( int who, String s ) { int person = who + 1; System.out.println( "Philosopher " + person + ", " + s ); } }