I have implemented the Dining Philosopher problem using Monitor (Synchronized) in Java.
The goal of this program is:
Every philosopher should follow the workflow of think, get chopsticks, eat, put chopsticks (no race conditions).
No Deadlock
I think this code seems to work fine but something is not right because it is run forever I tried to debug it and the debugging tool stop at this line philosopher[i].t.join(); but the program was not terminated.
Please help my identify the problem or show me how to fix it. Thank you for your advice.
MyMonitor class:
class MyMonitor {
private enum States {THINKING, HUNGRY, EATING};
private States[] state;
public MyMonitor() {
state = new States[5];
for(int i = 0; i < 5; i++) {
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
}
}
private void test(int i) {
if((state[(i+4)%5]!=States.EATING) && (state[i]==States.HUNGRY) && (state[(i+1)%5]!=States.EATING)) {
state[i] = States.EATING;
System.out.println("Philosopher " + i + " is EATING");
notify();
}
}
public synchronized void pickup(int i) {
state[i] = States.HUNGRY;
System.out.println("Philosopher " + i + " is HUNGRY");
test(i);
if (state[i] != States.EATING) {
System.out.println("Philosopher " + i + " is WAITING");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void putdown(int i) {
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
test((i+4)%5);
test((i+1)%5);
}
}
MyPhilosopher class:
class MyPhilosopher implements Runnable{
private int myID;
private int eatNum;
private MyMonitor monitor;
private Thread t;
public MyPhilosopher(int myID, int eatNum, MyMonitor monitor) {
this.myID = myID;
this.eatNum = eatNum;
this.monitor = monitor;
t = new Thread(this);
t.start();
}
public void run() {
int count = 1;
while(count <= eatNum ){
monitor.pickup(myID);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
monitor.putdown(myID);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
public static void main(String[] args) {
int eatNum = 10;
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("xxx");
System.out.println("xxx");
System.out.println("xxx");
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("Starting");
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("");
MyMonitor monitor = new MyMonitor();
MyPhilosopher[] philosopher = new MyPhilosopher[5];
for(int i = 0; i < 5; i++) {
philosopher[i] = new MyPhilosopher(i, eatNum, monitor);
}
for(int i = 0; i < 5; i++) {
try {
philosopher[i].t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("Ended");
}
}
I have executed your code and it runs perfectly until two or more executions. In addition, you can decrease the sleep time, your code is correct but perfect until 4 pilosophers are waiting and one of them is eating. I don't like it. You are breaking out one coffman condition but i recomend you to use other implementations as by breaking hold and wait conditions. I mean, you can take both chopsticks or none, other implementation can be, even pilosophers take the chopsticks on the right and the odd pilosophers take the left one. Good Luck!
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 2 is THINKING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 1 is THINKING
----------------------------------------------------------------------------------------------------
Ended
But,i have checked that you have a deadlock in some special condition like this: When all philosophers least one can eat and others are waiting. But i have changed your code in test by using synchronize in the header of the function, the if condition of the test() method by while and in the method putdown() i have changed the notify by notifyAll(); The code is this:
class MyMonitor {
private enum States {THINKING, HUNGRY, EATING};
private States[] state;
public MyMonitor() {
state = new States[5];
for(int i = 0; i < 5; i++) {
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
}
}
private synchronized void test(int i) {
while((state[(i+4)%5]!=States.EATING) && (state[i]==States.HUNGRY) && (state[(i+1)%5]!=States.EATING)) {
state[i] = States.EATING;
System.out.println("Philosopher " + i + " is EATING");
// notify();
}
}
public synchronized void pickup(int i) {
state[i] = States.HUNGRY;
System.out.println("Philosopher " + i + " is HUNGRY");
test(i);
if (state[i] != States.EATING) {
System.out.println("Philosopher " + i + " is WAITING");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void putdown(int i) {
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
//test((i+4)%5);
//test((i+1)%5);
notifyAll();
}
}
I advise you to use one or more implementations and before thinking what coffman condition do you want to break. Good luck