2017-03-19 12 views
2

私はCのposixスレッドを使用しています。問題が発生しました。私はそれほど理解しておらず、何が問題なのかを知りたいです。pthread mutexが待ち状態でロック解除していません

要約すると、私は3つのスレッドを作成して、プログラムの状態を確認し、準備ができていることを知らせ、さらに信号を待っています。一方、これらのスレッドを作成したスレッドは、それぞれのスレッドがセットアップされたことを通知するために待機しています(pthread_cond_wait_)。しかし、一度待ってからプログラムが完全に停止すると、ミューテックスは決してロックされないようです。

これは、メインスレッドのコードです:ここで

pthread_mutex_lock(&scenario->mutex); 
    if (scenario->flags.sinkThreadSetup == 0) { 
     pthread_create(&sinkT, NULL, sinkProblemHandler, (void *)scenario); 
     pthread_cond_wait(&scenario->sinkSetupCondition, &scenario->mutex); 
    } 
    if (scenario->flags.freeThreadSetup == 0) { 
     pthread_create(&freeT, NULL, freeWheelProblemHandler, (void *)scenario); 
     pthread_cond_wait(&scenario->freeSetupCondition, &scenario->mutex); 
    } 
    if (scenario->flags.blockThreadSetup == 0) { 
     pthread_create(&blockT, NULL, blockProblemHandler, (void *)scenario); 
     pthread_cond_wait(&scenario->blockSetupCondition, &scenario->mutex); 
    } 
    scenario->state = VECTORING; 
    pthread_mutex_unlock(&scenario->mutex); 

    // Start wheel threads 
    pthread_t wheelThreads[NUM_WHEELS]; 
    scenario_wheel_t threadDataArr[NUM_WHEELS]; 
    for (int i =0; i < NUM_WHEELS; i++) { 
     threadDataArr[i].scenario = scenario; 
     threadDataArr[i].wheel = &scenario->wheels[i]; 
     pthread_create(&wheelThreads[i], NULL, wheel_start, (void *)&threadDataArr[i]); 
    } 
    pthread_mutex_lock(&scenario->mutex); 
    pthread_cond_wait(&scenario->scenarioComplete_condition, &scenario->mutex); 
    pthread_mutex_unlock(&scenario->mutex); 

は、問題のハンドラスレッドのコードです:

void *sinkProblemHandler(void *args) { 
    scenario_t *scenario = (scenario_t *) args; 
    while(scenario->flags.terminate != 1) { 
     pthread_mutex_lock(&scenario->mutex); 
     if (scenario->state == SETUP && scenario->flags.sinkThreadSetup == 0) { 
      scenario->flags.sinkThreadSetup = 1; 
      pthread_cond_signal(&scenario->sinkSetupCondition); 
     } 
     if (scenario->state != SINKING) { 
      pthread_cond_wait(&scenario->conditions.sinking_condition, &scenario->mutex); 
      if (scenario->flags.terminate == 1) { 
       pthread_mutex_unlock(&scenario->mutex); 
       pthread_exit(NULL); 
      } 
      printf("SINKHandler: I'M HELPING!"); 
     } 
     pthread_mutex_unlock(&scenario->mutex); 
    } 
    pthread_exit(NULL); 
} 

void *blockProblemHandler(void *args) { 
    scenario_t *scenario = (scenario_t *) args; 
    while(scenario->flags.terminate != 1) { 
     pthread_mutex_lock(&scenario->mutex); 
     if (scenario->state == SETUP && scenario->flags.blockThreadSetup == 0) { 
      scenario->flags.blockThreadSetup = 1; 
      pthread_cond_signal(&scenario->blockSetupCondition); 
     } 
     if (scenario->state != BLOCKED) { 
      pthread_cond_wait(&scenario->conditions.blocked_condition, &scenario->mutex); 
      if (scenario->flags.terminate == 1) { 
       pthread_mutex_unlock(&scenario->mutex); 
       pthread_exit(NULL); 
      } 
      printf("BlockHandler: I'M HELPING!"); 
     } 
     pthread_mutex_unlock(&scenario->mutex); 
    } 
    pthread_exit(NULL); 
} 

void *freeWheelProblemHandler(void * args) { 
    scenario_t *scenario = (scenario_t *) args; 
    while(scenario->flags.terminate != 1) { 
     pthread_mutex_lock(&scenario->mutex); 
     if (scenario->state == SETUP && scenario->flags.freeThreadSetup == 0) { 
      scenario->flags.freeThreadSetup = 1; 
      pthread_cond_signal(&scenario->freeSetupCondition); 
     } 
     if (scenario->state != BLOCKED) { 
      pthread_cond_wait(&scenario->conditions.freeWheeling_condition, &scenario->mutex); 
      if (scenario->flags.terminate == 1) { 
       pthread_mutex_unlock(&scenario->mutex); 
       pthread_exit(NULL); 
      } 
      printf("FreeHandler: I'M HELPING!"); 
     } 
     pthread_mutex_unlock(&scenario->mutex); 
    } 
    pthread_exit(NULL); 
} 

我々は問題ハンドラスレッドがそれぞれのセットアップを知らせることをここで見ることができます条件を満たしてから別の条件(pthread_cond_wait)を待つと、mutexのロックが解除されます。

私の初期の考えは、メインスレッドが待機を開始する前に問題ハンドラスレッドがシグナリングしていたため、デッドロックが発生するということでした。しかし、プログラムに接続した後では、プログラムは次のようになります。
1.問題のスレッドを開始します。
2.問題セットアップ条件(ロック解除ミューテックス)を待ちます。
3.問題ハンドラスレッドロックミューテックス。
3.問題ハンドラスレッドがシグナルを完了しました
4.問題ハンドラスレッドが待機します(おそらくmutexのロックを解除します)。
5.プログラムが完全に停止します。 (mutexがロックされていないなど)。

ご協力いただければ幸いです。 おかげ

+0

私が奇妙なのはあなたのメインプログラムの 'pthread_mutex_lock(&scenario-> mutex);'です。同じことをするスレッドでデッドロックが発生する可能性があります。 –

+0

メインスレッドのコードの最後には、他のすべてのスレッドが条件変数を待っているのを中断しています...そして、メインスレッドはmutexをロックして、条件を待っています。自分の条件で待っている。 (またはそれが現れる...私は何かを見逃していないことを確認するために慎重に見なかった) – Dmitri

+1

'wheel_start()'には何が入っていますか? – Dmitri

答えて

1

あなたのワーカースレッドは、およそすべてのロックが解除された後、ミューテックスがすぐにロックされている

while(var) { 
    pthread_mutex_lock(&scenario->mutex); 
    // ... 
    pthread_mutex_unlock(&scenario->mutex); 
} 

の形を持っています。メインスレッドは、ミューテックスを再取得できないため、実行を続ける機会はほとんどありません。

これはman pthread_cond_signalからのものである:

スケジューリングポリシー(該当する場合)に応じてミューテックスを求めて競合しなければならないブロック解除されているスレッド(S)、それぞれがpthread_mutex_lockのを呼び出したかのように()。

したがって、最小限でも、ワーカースレッドでmutexを再取得する前にpthread_yield()を試すことができます。ミューテックスの使用をさらに減らしたり、異なるセクションを並列に実行させるために異なるミューテックスを導入することもできます。

+1

スレッドが条件変数を待っている時間のほとんどを費やしている場合、それらは本当にmutexをロックしていないかもしれません...しかし、条件待ちの間に他のスレッドが自分の仕事をするのは、ループの前にロックしてからロックを解除する方が意味があるということです。 – Dmitri

関連する問題