I’m learning Concurrency in java and I’m trying to solve Dining-Philosopher problem with tryLock.
When I run the below code all 5 philosophers are starving.
Approach –
I’m using tryLock to acquire both left & right chopsticks(lock). If both chopsticks are acquired then I’m printing the Philosopher and chopstick’s order number. Else Philosopher is thinking.
OUTPUT
Philosopher 3 is thinking.
Philosopher 3 is thinking.
Philosopher 3 is thinking.
Philosopher 3 is thinking.
Philosopher 3 is thinking.
Philosopher 3 is thinking.
Philosopher 3 is thinking.
Philosopher 5 is thinking.
Philosopher 5 is thinking.
Philosopher 5 is thinking.
Philosopher 1 is thinking.
Philosopher 1 is thinking.
Philosopher 1 is thinking.
Philosopher 1 is thinking.
Philosopher 1 is thinking.
Philosopher 1 is thinking.
Philosopher 1 is thinking.
Philosopher 5 is thinking.
Philosopher 5 is thinking.
Philosopher 5 is thinking.
Philosopher 1 is thinking.
Main.java
package DiningPhilosophersProblem;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
private static final int TOTAL_PHILOSOPHERS = 5;
private static final int TOTAL_CHOPSTICKS = 5;
public static void main(String[] args) {
ArrayList<Chopstick> chopsticks = createChopSticks();
for (int i=0; i < TOTAL_PHILOSOPHERS; i++) {
Thread philosopherThread = new Thread(new PhilosopherTryLock(i+1, chopsticks));
philosopherThread.start();
}
}
private static ArrayList<Chopstick> createChopSticks() {
ArrayList<Chopstick> chopsticks = new ArrayList<>();
for (int i=0; i < TOTAL_CHOPSTICKS; i++) {
chopsticks.add(new Chopstick(i+1, new ReentrantLock()));
}
return chopsticks;
}
}
PhilosopherTryLock.java
package DiningPhilosophersProblem;
import java.util.ArrayList;
public class PhilosopherTryLock implements Runnable {
private int orderNo;
private ArrayList<Chopstick> chopsticks;
public PhilosopherTryLock(int orderNo ,ArrayList<Chopstick> chopsticks) {
this.orderNo = orderNo;
this.chopsticks = chopsticks;
}
@Override
public void run() {
while (true) {
Chopstick leftChopStick = chopsticks.get(getLeftChopStickIdx() - 1);
Chopstick rightChopStick = chopsticks.get(getRightChopStickIdx() - 1);
boolean leftChopStickAcquired = false;
boolean rightChopStickAcquired = false;
try {
leftChopStickAcquired = leftChopStick.getLock().tryLock();
rightChopStickAcquired = rightChopStick.getLock().tryLock();
if (leftChopStickAcquired && rightChopStickAcquired) {
System.out.println("Philosopher " + orderNo + " is eating with chopsticks "
+ leftChopStick.getOrderNo() + " and " + rightChopStick.getOrderNo());
Thread.sleep(1000);
}
else {
System.out.println("Philosopher " + orderNo + " is thinking.");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (leftChopStickAcquired) {
leftChopStick.getLock().unlock();
}
if (rightChopStickAcquired) {
rightChopStick.getLock().unlock();
}
}
}
}
private int getLeftChopStickIdx() {
return orderNo - 1 == 0 ? chopsticks.size() : orderNo - 1;
}
private int getRightChopStickIdx() {
return orderNo;
}
}
Chopstick.java
package DiningPhilosophersProblem;
import java.util.concurrent.locks.Lock;
public class Chopstick {
private int orderNo;
private Lock lock;
public Chopstick(int orderNo, Lock lock) {
this.orderNo = orderNo;
this.lock = lock;
}
public int getOrderNo() {
return orderNo;
}
public Lock getLock() {
return lock;
}
}
I was expecting that some Philosophers will be able to pick both chopsticks.