一般的には、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);
手順は
pthread_cond_wait(&cond, &mutex);
呼び出されると、ミューテックスのロックが解除されますスレッド2はミューテックスをロックし、
pthread_cond_signal()
ミューテックスのロックを解除する を呼び出します。スレッド1では、
pthread_cond_wait()
が呼び出され、ミューテックスを再度ロックします。
スレッド 2 では、pthread_cond_signal()
が呼び出された後、pthread_mutex_unlock(&mutex)
実行され、スレッド 1 によって現在ロックされているミューテックスのロックを解除しようとしているように見えます。私の理解に何か間違いがありますか?
pthread_cond_wait()
また、同じ cond-mutex ペアに対して 1 つのスレッドからしか呼び出せないようにも思えます。しかし、「pthread_cond_signal() 関数は、指定された条件変数 cond でブロックされているスレッドの少なくとも 1 つをブロック解除します (cond でブロックされているスレッドがある場合)」という記述があります。つまり、pthread_cond_wait()
同じ cond-mutex ペアに対して複数のスレッドから呼び出せるということですか?
ベストアンサー1
pthread_cond_signal
ミューテックスのロックを解除しません (ミューテックスへの参照がないので、何をロック解除すればよいのかをどうやって知ることができるのでしょうか)。実際、シグナルはミューテックスに接続する必要はありません。シグナリング スレッドはミューテックスを保持する必要はありませんが、条件変数に基づくほとんどのアルゴリズムでは保持されます。
pthread_cond_wait
ミューテックスはスリープする直前にロック解除されます (ご指摘のとおり) が、シグナルが送られると、ウェイクアップする前にミューテックスを再取得します (待機が必要になる場合があります)。したがって、シグナル スレッドがミューテックスを保持している場合 (通常の場合)、待機中のスレッドは、シグナル スレッドもミューテックスのロックを解除するまで処理を続行しません。
条件変数の一般的な使用法は次のようになります。
thread1:
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 番目のスレッドは、条件を真にする可能性のある操作を実行しているため、それを待機している可能性のあるすべてのスレッドを起動する必要があります。