## maldemer

I need to do a pretty standard dining philosophers setup for my class. (I assume most people on here know what this problem is... if not look here: http://en.wikipedia.org/wiki/Dining_philosophers_problem)
We need to have a variable number of philosophers between 2 and 8, and avoid deadlock and starvation.
In my design, each philosopher thread asks a Monitor class whether it can eat.
The monitor class knows which chopsticks are to the left and right of the requesting philosopher,
so it checks whether the left chopstick is free. If not, it waits three seconds, puts it down, and tries again.
If it is free, it tries to pick up the right chopstick. If it's free, great! The philosopher eats. If it's not free, the philosopher puts down the left chopstick. Then he tries all over again.
Each philosopher is supposed to go through the cycle five times. But my code is freezing really early. There seems to be some kind of deadlock, because the last printed output is "Philosopher #i is hungry and looking for chopsticks." Like this:

Philosopher #1 is thinking deep thoughts.
Philosopher #2 is thinking deep thoughts.
Philosopher #3 is thinking deep thoughts.
Philosopher #2 is hungry and looking for chopsticks.
Philosopher #2 is eating.
Philosopher #3 is hungry and looking for chopsticks.
Philosopher #1 is hungry and looking for chopsticks.

``````public class Philosopher implements Runnable {

public final int EATS = 5;
private int philNum;
private int timesEaten;
private Monitor m;
private int state; // 0=thinking, 1=hungry, 2=eating, 3=stuffed

Philosopher(int num, Monitor mon) {
philNum = num;
m=mon;
state=0;
}

public int getPhilNum() {
return philNum;
}

public void run () {
try {
// Do I need to put this in a while loop?
for (int i=0; i<EATS; i++) {
System.out.println("Philosopher #"+philNum+" is thinking deep thoughts.");
Thread.sleep((long)Math.random()*3000); // The philosopher is thinking
state=1; // The philosopher gets hungry
// The philosopher tells the view to change his state
System.out.println("Philosopher #"+philNum+" is hungry and looking for chopsticks.");
m.requestEat(philNum); // The philosopher asks the monitor if he can eat
System.out.println("Philosopher #"+philNum+" is eating.");
state=2;
Thread.sleep((long)Math.random()*2000); // The philosopher is eating
m.stopEating(philNum);
state=3;
System.out.println("Philosopher #"+philNum+" is stuffed and putting down his chopsticks.");
Thread.sleep((long)Math.random()*2000); // The philosopher is stuffed
state=0;
timesEaten++;
if (timesEaten==5) System.out.println("PHILOSOPHER #"+philNum+" HAS EATEN "+timesEaten+" TIMES.");
else System.out.println("Philosopher #"+philNum+" has eaten "+timesEaten+" times.");
}
}
catch (InterruptedException e) { }

}
}

import java.util.concurrent.locks.*;
import java.util.concurrent.*;

public class Chopstick {

private boolean inUse=false;
private int stickNum;
private ReentrantLock lock = new ReentrantLock();
private Condition chopstickAvailableCondition = lock.newCondition();

Chopstick(int num) {
stickNum=num;
}

synchronized boolean isInUse() {
return inUse;
}

synchronized void putDown() {
inUse=false;
chopstickAvailableCondition.signal();
lock.unlock();
}

synchronized boolean pickUp() {
try {
lock.lock();
if (inUse) {
if (chopstickAvailableCondition.await(3, TimeUnit.SECONDS)) {
inUse=true;
return true;
}
else {
lock.unlock();
return false;
}
}
else {
inUse=true;
return true;
}
}
catch (InterruptedException e) { return false; }
}

}

import java.util.*;

public class Monitor {

private int numPhils;
Chopstick[] chopsticks;

Monitor(int numOfPhils) {
numPhils=numOfPhils;
chopsticks = new Chopstick[numPhils];
for (int i=0; i<numPhils; i++) {
chopsticks[i]=new Chopstick(i+1);
}
philQueue = new LinkedList<Philosopher>();
}

synchronized boolean requestEat(int pNum) {
int currentPhil=pNum;
int left = pNum-1; // The INDEX position of the chopstick with the same number, so subtract 1
int right;
if (pNum==numPhils) right = 0;
else right = pNum; // The INDEX position of the chopstick with (the philosopher's number + 1)
boolean success=false;
if (chopsticks[left].pickUp()) {
if (chopsticks[right].pickUp()) {
success=true;
}
else chopsticks[left].putDown();
}
return success;
}

synchronized void stopEating(int pNum) {
int left = pNum-1;
int right;
if (pNum==numPhils) right = 0;
else right = pNum;
chopsticks[left].putDown();
chopsticks[right].putDown();
}

synchronized boolean checkChopsticks(int pNum) {
int left = pNum-1;
int right;
if (pNum==numPhils) right = 0;
else right = pNum;
if (!chopsticks[left].isInUse() && !chopsticks[right].isInUse()) return true;
else return false;
}

}

public class DinnerMain {

public static void main (String[] args) {
try {
int numPhils = Integer.parseInt(args[0]);
Monitor m;
if (numPhils >= 2 && numPhils <= 8) {
m = new Monitor(numPhils);
Philosopher[] philosophers = new Philosopher[numPhils];
for (int i=0; i<numPhils; i++) {
philosophers[i]=new Philosopher(i+1, m);
}
for (int i=0; i<numPhils; i++) {
}
}
else {
System.out.println("Your argument was not an integer between 2 and 8." +
"Please try again with a valid command line argument.");
}

}
catch (NumberFormatException e) {
System.out.println("Your argument was not an integer between 2 and 8." +
"Please try again with a valid command line argument.");
}
}

}``````

## NormR1 563

Lots of logic to follow.
Have you tried debugging by adding more println()s to show code flow and variable states?

## maldemer

Lots of logic to follow.
Have you tried debugging by adding more println()s to show code flow and variable states?

Yes, I've tried... I've never debugged with multiple threads before, and it's a bit confusing. Besides, since no exceptions are thrown, it's difficult for me to tell exactly where things are going wrong.

I don't think print statements would really help either, because there seems to be some kind of deadlock between threads going on. But I'll try.

I know it's a lot of logic to follow... It's hard to explain in any more concise terms though!

## NormR1 563

Comments in the code describing why your doing things helps others understand why you are doing things.

I don't think print statements would really help either, because there seems to be some kind of deadlock between threads going on.

Its not magic. You have to follow each thread to where it hangs and see why. Some count is wrong causing a wait that shouldn't happen for example.