I'm having trouble with the deadlock problem with threads. It seems the problem is about how threads work. I have 2 questions here.
Although I created 5 threads and start them, not all of them call
run(). It's random but I don't know why.There's a problem with the
while()in main method, my code keeps running unlimited even I set the end condition.
It would be so great if you can help me.
Here my class Chopstick
static class Chopstick {
public Semaphore mutex = new Semaphore(1);
void grab() {
try {
mutex.acquire();
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
void release() {
mutex.release();
}
}
Here my class Philosopher (aka Thread). I used resources hierarchy solution that the odd philosopher needs to pick up the left chopstick first and then the right one, the even picks up the right.
static class Philosopher extends Thread {
public boolean eaten = false;
public int number;
public Chopstick leftChopstick;
public Chopstick rightChopstick;
public Philosopher(int number, Chopstick leftChopstick, Chopstick rightChopstick) {
this.number = number;
this.leftChopstick = leftChopstick;
this.rightChopstick = rightChopstick;
}
public void run() {
int phils=5;
while (true) {
if (number % 2 == 1) {
leftChopstick.grab();
System.out.println("Philosopher " + number + " grabs chopstick " + number);
rightChopstick.grab();
System.out.println("Philosopher " + number + " grabs chopstick " + (number+1)%phils);
eat();
leftChopstick.release();
System.out.println("Philosopher " + number + " releases chopstick " + number );
rightChopstick.release();
System.out.println("Philosopher " + number + " releases chopstick " +(number+1)%phils);
} else {
leftChopstick.grab();
System.out.println("Philosopher " + number + " grabs chopstick " + (number+1)%phils);
rightChopstick.grab();
System.out.println("Philosopher " + number + " grabs chopstick " + number );
eat();
leftChopstick.release();
System.out.println("Philosopher " + number + " releases chopstick " + (number+1)%phils);
rightChopstick.release();
System.out.println("Philosopher " + number + " releases chopstick " + number );
}
}
}
void eat() {
try {
int sleepTime = ThreadLocalRandom.current().nextInt(0, 1000);
System.out.println("Philosopher " + number + " eats for " + sleepTime+"s");
Thread.sleep(sleepTime);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
And my main class:
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadLocalRandom;
public class Test {
static int number = 5;
static Philosopher phils[] = new Philosopher[number];
static Chopstick chopstick[] = new Chopstick[number];
public static void main(String args[]) {
for (int i = 0; i < number; i++) {
chopstick[i] = new Chopstick();
}
for (int i = 0; i < number; i++) {
if (i % 2 == 0) {
phils[i] = new Philosopher(i, chopstick[(i + 1) % number], chopstick[i]);
} else {
phils[i] = new Philosopher(i, chopstick[i], chopstick[(i + 1) % number]);
}
phils[i].start();
}
while (true) {
try {
boolean isAllEaten = true;
for (Philosopher p : phils) {
if (!p.eaten) {
isAllEaten = false;
break;
}
}
if (isAllEaten) {
System.out.println("Everyone Eats");
break;
}
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
System.out.println("Exit The Program!");
System.exit(0);
}
}