0

私は哲学者の食事のタスクに取り組んでいますが、問題があります。私のコードは、フォーク、哲学者、dinerTable の 3 つのクラスを中心に展開しています (はい、最後の 2 つを誤って小文字で名前を付けました)。

コードは適切に開始され、哲学者 0 と 2 はフォークをつかみますが、その後コードは停止します。誰か助けてもらえますか?

3 つのクラスがあります。

フォーク (スレッドを拡張) :

public synchronized boolean isFree() throws InterruptedException
{
    return available;

}

public synchronized void returnFork() throws InterruptedException
{
    available = true;
    this.notify();
}

public synchronized void takeFork() throws InterruptedException
{
    available = false;
    this.notify();
}

哲学者 (Runnable を実装) :

    private int number;
private Forks right;
private Forks left;
private boolean hasBothForks;
private boolean keepGoing;

public boolean isKeepGoing() {
    return keepGoing;
}

public void setKeepGoing(boolean keepGoing) {
    this.keepGoing = keepGoing;
}

public philosophers(int number,Forks right, Forks left, boolean keepGoing)
{
    this.number = number;
    this.right = right;
    this.left = left;
    hasBothForks = false;
    this.keepGoing = keepGoing;
}

private void print(String message)
{
    System.out.println("Philosopher " + number + " " + message );

}

@Override
public void run() {
    if(keepGoing == true)
    {
        try
        {


            print("is hungry");
            print( "checks if forks are free");
            if(right.isFree() == true && left.isFree() == true && hasBothForks == false)
            {
                print("is grabbing forks");
                right.takeFork();
                left.takeFork();
                hasBothForks = true;
            } // end if
            else if(hasBothForks == true)
            {
                print("is eating");
                Thread.sleep(2000);
                print("is putting down left fork");
                left.returnFork();
                print("is putting down right fork");
                right.returnFork();
                print("is finished eating");
                hasBothForks = false;
            } // end if
            else if(right.isFree() == false && left.isFree() == false && hasBothForks == false)
                {
                    print("is thinking");
                    Thread.sleep(2000);
                } // end if             

        } // end try
        catch (InterruptedException e) {

                    print(" is interrupted");

        } // end catch
    } // end if


} // end run

ダイナーテーブル:

private static int num = 5;
private static Forks right = null;
private static Forks left = null;
private static Forks[] forks = new Forks[num];
private static philosophers[] philosophers = new philosophers[num];

public static void main(String args[])
{
    for (int i = 0; i < num ; i++)
    {
        forks[i] = new Forks();
    }
        for (int i = 0; i < num; i++)
        {
            if (i > 0)
            {
                left = forks[i - 1];
                right = forks[i];
            } // end if
            else if ( i == 0)
            {
                left = forks[num-1];
                right = forks[i];
            } // end if

            philosophers[i] = new philosophers(i, right, left, true);

            Thread thread = new Thread(philosophers[i]);
            thread.start();

        } // end for

        System.out.print("\n");
}
4

2 に答える 2

2

コメントを投稿できないため、これに回答を投稿しています。

これに関する最初の問題は、スレッド同期がないことです。競合状態のために、すべての哲学者が両方のフォークを取得する可能性があります。

if(right.isFree() == true && left.isFree() == true && hasBothForks == false)
{
    print("is grabbing forks");
    right.takeFork();
    left.takeFork();
    hasBothForks = true;
}

この順序で発生した場合:

P1: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P2: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P3: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P4: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler
P5: right.isFree() == true, left.isFree() == true, hasBothForks == false - thread is slept by the scheduler

P1: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P2: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P3: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P4: right.takeFork(), left.takeFork() - thread is slept by the scheduler
P5: right.takeFork(), left.takeFork() - thread is slept by the scheduler

編集:

このスレッドの問題に対する解決策は 2 つあります。

まず、フォークは実際にはMutexまたはSemaphoreとして知られるスレッドセーフなオブジェクトであることを意図しています。これは、フォークごとに 1 つのトークンしか使用できないことを意味し、このフォークを要求する他のユーザーは、トークンが使用可能になるまで待たなければなりません。

第二に、飢餓を引き起こす可能性があるため、哲学者が全員が最初に左のフォークを選択したり、全員が最初に右のフォークを選択したりしないようにする方法が必要です。代わりに、奇数の哲学者を左利きにする (最初に左のフォークをつかむ)、偶数の哲学者を右利きにする (最初に右のフォークをつかむ) などの解決策を考え出す必要があります。

これらの 2 つの問題を修正すると、少なくとも 1 人の哲学者が食べられるようになり、彼が食べ終わると両方のフォーク (セマフォを読み取る) が解放され、他の哲学者がフォークを取得できるようになります。

編集2:

私が提案したソリューションの詳細な説明は、http ://www.cs.mtu.edu/~shene/NSF-3/e-Book/MUTEX/TM-example-left-right.html にあります。

于 2013-05-07T00:16:22.540 に答える