ノート:食事する哲学者の問題
表示
Javaでの解法の実装について
[編集]この記事にはJavaでセマフォを用いた解法の例が提示されていますが、コードに一部誤りがあるのではないかと考えています。具体的にはセマフォからもらうパーミットの数が2つになるべきではないかという点です。
記事に示されているコードでは
sem.acquire();
という文で1つのパーミットを得ようとしますが、そもそもセマフォは5つのパーミットを持つように初期化されているので、この状態では5人の哲学者が1本のフォークだけを使って自由に食事ができる形になると思います。
従いまして、acquireおよびreleaseするパーミットの数を使用するフォークの数である2つに変更する必要があると思います。
念のため、私が正しいと思うコードを以下に示しておきます。少し実装が変わっているのはご了承ください。
import java.util.*;
import java.util.concurrent.Semaphore;
public class DiningPhilosophers {
public static void main(String... args) {
new DiningPhilosophers(5);
}
private Semaphore sem;
public DiningPhilosophers(int n) {
sem = new Semaphore(n, true);
Philosopher[] philos = new Philosopher[n];
for(int i=0; i<n; i++) {
philos[i] = new Philosopher(i, sem);
philos[i].start();
}
for(int i=0; i<n; i++) {
try {
philos[i].join();
} catch(InterruptedException e) {}
}
System.out.println("All philosophers finished eating!!");
}
}
class Philosopher extends Thread {
private static Random rand = new Random(System.currentTimeMillis());
private static int nForks = 2;
private int id;
private Semaphore sem;
public Philosopher(int id, Semaphore sem) {
this.id = id;
this.sem = sem;
}
private void think() {
System.out.printf("Philosopher %d is thinking...\n", this.id);
try {
Thread.sleep(rand.nextInt(2000));
} catch(InterruptedException e) {}
}
private void eat() {
System.out.printf("Philosopher %d is eating !!\n", this.id);
try {
Thread.sleep(rand.nextInt(2000));
} catch(InterruptedException e) {}
}
public void run() {
for(int i=0; i<3; i++) {
think();
try {
sem.acquire(nForks);
} catch(InterruptedException e) {
e.printStackTrace();
}
eat();
sem.release(nForks);
}
}
}
もし私の不勉強で、コードが誤りでないという場合にはお知らせ願えますと幸いです。よろしくお願いいたします。--Runner3494(会話) 2014年6月1日 (日) 19:38 (UTC)