0

C++ を使用してダイニング哲学者の問題を解決しようとしています。

コードは でコンパイルされg++ -lpthreadます。

全体のソリューションは哲学者の githubにあります。リポジトリには、main.cpp と philosopher.cpp の 2 つの cpp ファイルが含まれています。「Main.cpp」は、ミューテックス変数、セマフォ、5 つの条件変数、5 つのフォークを作成し、哲学者を開始します。セマフォは、哲学者の開始を同期するためにのみ使用されます。他のパラメーターは、問題を解決するために哲学者に渡されます。「Philosopher.cpp」には、特定の問題の解決策が含まれていますが、数ステップ後にデッドロックが発生します。

デッドロックは、哲学者 0 が食事をしていて、哲学者 1 (彼の隣) がフォークを取りたいときに発生します。次に、哲学者 1 はミューテックスを取得し、哲学者 0 がフォークを下ろすまでそれを返しません。哲学者 0 は、ミューテックスを取得したためにフォークを下に置くことができないため、デッドロックが発生します。問題はPhilosopher::take_fork メソッドにあり、 pthread_cond_wait(a,b) の呼び出しがミューテックス b を解放していません。理由がわからない?

// Taking fork. If eather lef or right fork is taken, wait.
void Philosopher::take_fork(){
  pthread_mutex_lock(&mon);
  std::cout << "Philosopher " << id << " is waiting on forks" << std::endl;
  while(!fork[id] || !fork[(id + 1)%N])
    pthread_cond_wait(cond + id, &mon);
  fork[id] = fork[(id + 1)%N] = false;
  std::cout << "Philosopher " << id << " is eating" << std::endl;
  pthread_mutex_unlock(&mon);
}

残りはこのコードを参照してください。

4

1 に答える 1

1

への呼び出しpthread_cond_wait()は問題ないので、問題は別の場所にあるはずです。私が見ることができる 3 つのバグがあります。

まず、配列内の最初のmain()条件変数のみを初期化しています。すべての条件変数を初期化する必要があります。N

for(int i = 0; i < N; i++) {
    fork[i] = true;
    pthread_cond_init(&cond[i], NULL);
}

pthread_mutex_init(&mon, NULL);

次に、put_fork()条件変数の 1 つを通知するための計算が正しくありません。

pthread_cond_signal(cond + (id-1)%N);    /* incorrect */

idがゼロに等しい場合は(id - 1) % N-1 に等しいため、これは を通知しようとしますが、これは条件変数を指していません (スタックのcond - 1直前に配置される可能性があるため、このポインターが実際にミューテックスを破壊する可能性があります)。 cond. 実際に必要な計算は次のとおりです。

pthread_cond_signal(cond + (id + N - 1) % N);

3 番目のバグはデッドロックの原因ではありませんが、呼び出すsrand(time(NULL))たびに呼び出すべきではありませrand()main()

于 2013-02-25T05:45:01.907 に答える