コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

ノート:食事する哲学者の問題

ページのコンテンツが他言語でサポートされていません。

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)[返信]