Introduction
The Dining Philosophers Problem illustrates concurrency challenges, where philosophers seated at a table must pick up chopsticks to eat, leading to potential deadlock.
Solution
- Chopstick Class: Implements locking mechanisms for chopstick pickup and put down.
public class Chopstick {
private final Lock lock = new ReentrantLock();
private final Logger logger = LoggerFactory.getLogger(Chopstick.class);
public boolean pickUp() {
try {
return lock.tryLock(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
public void pickDown() {
lock.unlock();
}
}
- Philosopher Class: Represents each philosopher, managing chopstick pickup and eating.
public class Philosopher implements Runnable {
private final Logger logger = LoggerFactory.getLogger(Philosopher.class);
private int id;
private Chopstick leftStick;
private Chopstick rightStick;
public Philosopher(int id, Chopstick leftStick, Chopstick rightStick) {
this.id = id;
this.leftStick = leftStick;
this.rightStick = rightStick;
}
@Override
public void run() {
while (true) {
try {
logger.info("Philosopher " + id + " is thinking.");
if (leftStick.pickUp()) {
logger.info("Philosopher " + id + " picked up left stick.");
if (rightStick.pickUp()) {
logger.info("Philosopher " + id + " picked up right stick.");
logger.info("Philosopher " + id + " is eating.");
rightStick.pickDown();
logger.info("Philosopher " + id + " pick down right stick.");
}
leftStick.pickDown();
logger.info("Philosopher " + id + " pick down left stick.");
}
} catch (Exception e) {
Thread.currentThread().interrupt();
return;
}
}
}
}
- Main Class (Driver): Sets up philosophers and chopsticks, employing thread pooling for execution.
public class Driver {
private static final Logger logger = LoggerFactory.getLogger(Driver.class);
private static final Philosopher[] philosophers = new Philosopher[5];
private static final Chopstick[] chopsticks = new Chopstick[5];
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(5, runnable -> {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setPriority(Thread.MAX_PRIORITY);
return thread;
});
for (int i = 0; i < chopsticks.length; i++) {
chopsticks[i] = new Chopstick();
}
for (int i = 0; i < philosophers.length; i++) {
philosophers[i] = new Philosopher(i + 1, chopsticks[i], chopsticks[(i + 1) % 5]);
executorService.execute(philosophers[i]);
}
}
}
Conclusion
By synchronizing chopstick access and implementing a thoughtful eating protocol, we ensure the philosophers can dine peacefully without encountering deadlock or contention issues.
Register
Your article helped me a lot, is there any more related content? Thanks!