Java 餐饮哲学家与协调员陷入僵局
Java Dining Philosophers Dead Lock with Koordinator
我有哲学家就餐问题。我想用 Monitor
来解决它。 Monitor
协调左右分叉的访问。
Monitor 使用 Array fork
表示每个 Philosoph 的分叉数量。
如果哲学家 i
可以的话 (fork[i] == 2
) 他会拿他邻居的一把叉子。如果他放叉子,条目将再次增加。
这是我的哲学家代码:
public class Philosoph {
protected volatile boolean isRunning = true;
protected final int id;
protected final Fork leftFork;
protected final Fork rightFork;
protected int eatCounter;
public Philosoph(int id, Fork leftFork, Fork rightFork) {
this.id = id;
this.leftFork = leftFork;
this.rightFork = rightFork;
eatCounter = 0;
}
public void eat() throws InterruptedException {
eatCounter++;
TimeUnit.MILLISECONDS.sleep(10);
}
public void think() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(5);
}
public void stop() {
isRunning = false;
}
}
public class KoordinierterPhilosph extends Philosoph implements Callable<Integer> {
Koordinator kord;
public KoordinierterPhilosph(Koordinator kord, int id, Fork leftFork, Fork rightFork) {
super(id, leftFork, rightFork);
this.kord = kord;
}
@Override
public Integer call() throws Exception {
while (isRunning) {
try {
think();
kord.takeFork(id);
eat();
kord.releaseFork(id);
} catch (InterruptedException ex) {
break;
}
}
return eatCounter;
}
}
这是我的显示器Class:
public class Koordinator {
private int[] forks;
private int anzahlPhilosophen;
private ReentrantLock lock = new ReentrantLock();
private Condition[] readyToEatCondition;
public Koordinator(int anzahlPhilosophen) {
this.anzahlPhilosophen = anzahlPhilosophen;
forks = new int[anzahlPhilosophen];
readyToEatCondition = new Condition[anzahlPhilosophen];
for (int i = 0; i < anzahlPhilosophen; i++) {
forks[i] = 2;
readyToEatCondition[i] = lock.newCondition();
}
}
public void takeFork(int id) throws InterruptedException {
while (forks[id] != 2) {
readyToEatCondition[id].await();
}
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] - 1;
if (id - 1 == -1) {
id = anzahlPhilosophen - 1;
} else {
id = id - 1;
}
forks[id] = forks[id] - 1;
}
public void releaseFork(int id) {
int idNew = 0;
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] + 1;
if (id - 1 == -1) {
idNew = anzahlPhilosophen - 1;
} else {
idNew = id - 1;
}
forks[idNew] = forks[idNew] + 1;
if (forks[(id + 1) % anzahlPhilosophen] == 2) {
readyToEatCondition[(id + 1) % anzahlPhilosophen].signal();
}
if (forks[idNew] == 2) {
readyToEatCondition[idNew].signal();
}
}
}
这是我的主要例程:
public class Runner {
private static ExecutorService threadPool;
private static int gesamt = 0;
public static void main(String[] args) {
ExecutorService serv = Executors.newCachedThreadPool();
try {
dining(5, serv);
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(Ue7.DiningPhilosopher.Alg3.Runner.class.getName()).log(Level.SEVERE, null, ex);
}
serv.shutdown();
}
public static void dining(int anzahlPhilosopher, ExecutorService pool) throws InterruptedException, ExecutionException {
threadPool = pool;
Map<String, Future<Integer>> result = new HashMap<>();
KoordinierterPhilosph[] philosopher = new KoordinierterPhilosph[anzahlPhilosopher];
Koordinator kord = new Koordinator(anzahlPhilosopher);
for (int i = 0; i < anzahlPhilosopher; i++) {
philosopher[i] = new KoordinierterPhilosph(kord, i, null, null);
}
for (int i = 0; i < anzahlPhilosopher; i++) {
result.put("Philosoph " + i, threadPool.submit(philosopher[i]));
}
TimeUnit.SECONDS.sleep(10);
for (KoordinierterPhilosph p : philosopher) {
p.stop();
}
for (Map.Entry pair : result.entrySet()) {
Future<Integer> f = (Future<Integer>) pair.getValue();
int eatPro = f.get();
gesamt += eatPro;
System.out.println(pair.getKey() + " " + eatPro);
}
System.out.println("Gesamt: " + gesamt);
}
}
但我总是遇到死锁,但现在不知道为什么
我找到问题了。我需要在Monitor
的Methods开头做一个lock
。有了它我就成了 Illegal State Exception
.
监视器现在看起来像这样:
public class Koordinator {
private int[] forks;
private int anzahlPhilosophen;
private ReentrantLock lock = new ReentrantLock();
private Condition[] readyToEatCondition;
public Koordinator(int anzahlPhilosophen) {
this.anzahlPhilosophen = anzahlPhilosophen;
forks = new int[anzahlPhilosophen];
readyToEatCondition = new Condition[anzahlPhilosophen];
for (int i = 0; i < anzahlPhilosophen; i++) {
forks[i] = 2;
readyToEatCondition[i] = lock.newCondition();
}
}
public void takeForks(int id) throws InterruptedException {
this.lock.lock();
try {
while (forks[id] != 2) {
readyToEatCondition[id].await();
}
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] - 1;
forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] = forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] - 1;
} finally {
this.lock.unlock();
}
}
public void releaseForks(int id) {
this.lock.lock();
try {
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] + 1;
forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] = forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] + 1;
if (forks[(id + 1) % anzahlPhilosophen] == 2) {
readyToEatCondition[(id + 1) % anzahlPhilosophen].signalAll();
}
if (forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] == 2) {
readyToEatCondition[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen].signalAll();
}
} finally {
this.lock.unlock();
}
}
}
我有哲学家就餐问题。我想用 Monitor
来解决它。 Monitor
协调左右分叉的访问。
Monitor 使用 Array fork
表示每个 Philosoph 的分叉数量。
如果哲学家 i
可以的话 (fork[i] == 2
) 他会拿他邻居的一把叉子。如果他放叉子,条目将再次增加。
这是我的哲学家代码:
public class Philosoph {
protected volatile boolean isRunning = true;
protected final int id;
protected final Fork leftFork;
protected final Fork rightFork;
protected int eatCounter;
public Philosoph(int id, Fork leftFork, Fork rightFork) {
this.id = id;
this.leftFork = leftFork;
this.rightFork = rightFork;
eatCounter = 0;
}
public void eat() throws InterruptedException {
eatCounter++;
TimeUnit.MILLISECONDS.sleep(10);
}
public void think() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(5);
}
public void stop() {
isRunning = false;
}
}
public class KoordinierterPhilosph extends Philosoph implements Callable<Integer> {
Koordinator kord;
public KoordinierterPhilosph(Koordinator kord, int id, Fork leftFork, Fork rightFork) {
super(id, leftFork, rightFork);
this.kord = kord;
}
@Override
public Integer call() throws Exception {
while (isRunning) {
try {
think();
kord.takeFork(id);
eat();
kord.releaseFork(id);
} catch (InterruptedException ex) {
break;
}
}
return eatCounter;
}
}
这是我的显示器Class:
public class Koordinator {
private int[] forks;
private int anzahlPhilosophen;
private ReentrantLock lock = new ReentrantLock();
private Condition[] readyToEatCondition;
public Koordinator(int anzahlPhilosophen) {
this.anzahlPhilosophen = anzahlPhilosophen;
forks = new int[anzahlPhilosophen];
readyToEatCondition = new Condition[anzahlPhilosophen];
for (int i = 0; i < anzahlPhilosophen; i++) {
forks[i] = 2;
readyToEatCondition[i] = lock.newCondition();
}
}
public void takeFork(int id) throws InterruptedException {
while (forks[id] != 2) {
readyToEatCondition[id].await();
}
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] - 1;
if (id - 1 == -1) {
id = anzahlPhilosophen - 1;
} else {
id = id - 1;
}
forks[id] = forks[id] - 1;
}
public void releaseFork(int id) {
int idNew = 0;
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] + 1;
if (id - 1 == -1) {
idNew = anzahlPhilosophen - 1;
} else {
idNew = id - 1;
}
forks[idNew] = forks[idNew] + 1;
if (forks[(id + 1) % anzahlPhilosophen] == 2) {
readyToEatCondition[(id + 1) % anzahlPhilosophen].signal();
}
if (forks[idNew] == 2) {
readyToEatCondition[idNew].signal();
}
}
}
这是我的主要例程:
public class Runner {
private static ExecutorService threadPool;
private static int gesamt = 0;
public static void main(String[] args) {
ExecutorService serv = Executors.newCachedThreadPool();
try {
dining(5, serv);
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(Ue7.DiningPhilosopher.Alg3.Runner.class.getName()).log(Level.SEVERE, null, ex);
}
serv.shutdown();
}
public static void dining(int anzahlPhilosopher, ExecutorService pool) throws InterruptedException, ExecutionException {
threadPool = pool;
Map<String, Future<Integer>> result = new HashMap<>();
KoordinierterPhilosph[] philosopher = new KoordinierterPhilosph[anzahlPhilosopher];
Koordinator kord = new Koordinator(anzahlPhilosopher);
for (int i = 0; i < anzahlPhilosopher; i++) {
philosopher[i] = new KoordinierterPhilosph(kord, i, null, null);
}
for (int i = 0; i < anzahlPhilosopher; i++) {
result.put("Philosoph " + i, threadPool.submit(philosopher[i]));
}
TimeUnit.SECONDS.sleep(10);
for (KoordinierterPhilosph p : philosopher) {
p.stop();
}
for (Map.Entry pair : result.entrySet()) {
Future<Integer> f = (Future<Integer>) pair.getValue();
int eatPro = f.get();
gesamt += eatPro;
System.out.println(pair.getKey() + " " + eatPro);
}
System.out.println("Gesamt: " + gesamt);
}
}
但我总是遇到死锁,但现在不知道为什么
我找到问题了。我需要在Monitor
的Methods开头做一个lock
。有了它我就成了 Illegal State Exception
.
监视器现在看起来像这样:
public class Koordinator {
private int[] forks;
private int anzahlPhilosophen;
private ReentrantLock lock = new ReentrantLock();
private Condition[] readyToEatCondition;
public Koordinator(int anzahlPhilosophen) {
this.anzahlPhilosophen = anzahlPhilosophen;
forks = new int[anzahlPhilosophen];
readyToEatCondition = new Condition[anzahlPhilosophen];
for (int i = 0; i < anzahlPhilosophen; i++) {
forks[i] = 2;
readyToEatCondition[i] = lock.newCondition();
}
}
public void takeForks(int id) throws InterruptedException {
this.lock.lock();
try {
while (forks[id] != 2) {
readyToEatCondition[id].await();
}
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] - 1;
forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] = forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] - 1;
} finally {
this.lock.unlock();
}
}
public void releaseForks(int id) {
this.lock.lock();
try {
forks[(id + 1) % anzahlPhilosophen] = forks[(id + 1) % anzahlPhilosophen] + 1;
forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] = forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] + 1;
if (forks[(id + 1) % anzahlPhilosophen] == 2) {
readyToEatCondition[(id + 1) % anzahlPhilosophen].signalAll();
}
if (forks[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen] == 2) {
readyToEatCondition[(id - 1 + anzahlPhilosophen) % anzahlPhilosophen].signalAll();
}
} finally {
this.lock.unlock();
}
}
}