1. ホーム
  2. c++

[解決済み] pthread_cond_wait() と pthread_cond_signal() を理解する。

2022-03-03 11:24:15

質問

一般的に言えば pthread_cond_wait()pthread_cond_signal() は以下のように呼び出されます。

//thread 1:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
do_something()
pthread_mutex_unlock(&mutex);

//thread 2:
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);  
pthread_mutex_unlock(&mutex);

ステップの内容は

  1. pthread_cond_wait(&cond, &mutex); が呼ばれると、ミューテックスのロックが解除されます。

  2. スレッド 2 はミューテックスをロックし、次のように呼び出します。 pthread_cond_signal() であり、ミューテックスのロックを解除する。

  3. スレッド1では pthread_cond_wait() が呼び出され、再びミューテックスをロックします。

さて、スレッド 2 では、次のように pthread_cond_signal() が呼び出されます。 pthread_mutex_unlock(&mutex) が実行されると、スレッド1によってロックされているミューテックスのロックを解除したいように思えます。私の理解に何か間違いがあるのでしょうか?

また pthread_cond_wait() は、同じcond-mutexの組に対して1つのスレッドからしか呼び出されません。しかし、"The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond)." とあることから、この場合は pthread_cond_wait() は、同じcond-mutexの組に対して多くのスレッドから呼び出される可能性があるのですか?

どのように解決するのですか?

pthread_cond_signal は、ミューテックスのロックを解除しない(ミューテックスへの参照を持たないので解除できない。では、何を解除すればいいのかどうやって知ることができるのか?)。 シグナルを送るスレッドはミューテックスを保持する必要はありませんが、条件変数に基づくほとんどのアルゴリズムでは保持することになります。

pthread_cond_wait はスリープする直前にミューテックスのロックを解除しますが(ご指摘の通り)、その後、スリープから復帰する前に、シグナルを受けたときにミューテックスを再要求します(これは待つ必要があるかもしれません)。 ですから、もしシグナルを送るスレッドがミューテックスを保持している場合(通常の場合)、シグナルを送るスレッドがミューテックスのロックを解除するまで、待機中のスレッドは処理を進めません。

条件バーの一般的な使い方は、次のようなものです。

thread 1:
    pthread_mutex_lock(&mutex);
    while (!condition)
        pthread_cond_wait(&cond, &mutex);
    /* do something that requires holding the mutex and condition is true */
    pthread_mutex_unlock(&mutex);

thread2:
    pthread_mutex_lock(&mutex);
    /* do something that might make condition true */
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

2つのスレッドは、ミューテックスがアクセスを保護しているいくつかの共有データ構造を持っています。 最初のスレッドは、ある条件が真になるまで待ち、それからすぐに何らかの処理を行いたいとします(条件チェックと処理の間に他のスレッドが入り込んで条件を偽にするようなレースコンディションの機会はありません)。 2 番目のスレッドは、その条件が真になるような処理をしているので、それを待っている可能性のある人を起こす必要があります。