-
Notifications
You must be signed in to change notification settings - Fork 173
/
DiningPhilosophersProblem.java
90 lines (74 loc) · 2.95 KB
/
DiningPhilosophersProblem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;
public class DiningPhilosophers {
private static final Random random = new Random();
private final Semaphore diningSemaphore = new Semaphore(NUM_PHILOSOPHERS - 1);
public static final int NUM_PHILOSOPHERS = 5;
private final Lock[] chopsticks = new Lock[NUM_PHILOSOPHERS];
private enum Action {
THINKING("Thinking"),
PICKED_LEFT_CHOPSTICK("Picked up left chopstick"),
PICKED_RIGHT_CHOPSTICK("Picked up right chopstick"),
EATING("Eating"),
PUT_DOWN_LEFT_CHOPSTICK("Put down left chopstick"),
PUT_DOWN_RIGHT_CHOPSTICK("Put down right chopstick");
private final String actionString;
Action(String actionString) {
this.actionString = actionString;
}
@Override
public String toString() {
return actionString;
}
}
public DiningPhilosophers() {
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
chopsticks[i] = new ReentrantLock();
}
}
public void dine(int philosopherId) throws InterruptedException {
Lock leftChopstick = chopsticks[philosopherId];
Lock rightChopstick = chopsticks[(philosopherId + 1) % NUM_PHILOSOPHERS];
while (true) {
diningSemaphore.acquire();
// Attempt to pick up chopsticks
if (leftChopstick.tryLock()) {
try {
log(philosopherId, Action.PICKED_LEFT_CHOPSTICK);
if (rightChopstick.tryLock()) {
try {
log(philosopherId, Action.PICKED_RIGHT_CHOPSTICK);
// Both chopsticks acquired, eat
eat(philosopherId);
} finally {
rightChopstick.unlock();
log(philosopherId, Action.PUT_DOWN_RIGHT_CHOPSTICK);
}
}
} finally {
// Release the left chopstick
leftChopstick.unlock();
log(philosopherId, Action.PUT_DOWN_LEFT_CHOPSTICK);
}
diningSemaphore.release();
}
// Think before retrying
think(philosopherId);
}
}
private void log(int philosopherId, Action action) {
System.out.println("Philosopher " + philosopherId + ": " + action);
}
private void eat(int philosopherId) throws InterruptedException {
log(philosopherId, Action.EATING);
// Simulating eating to prevent livelock
Thread.sleep(random.nextInt(100));
}
private void think(int philosopherId) throws InterruptedException {
log(philosopherId, Action.THINKING);
// Simulating thinking
Thread.sleep(random.nextInt(100));
}
}