一般的に、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);
が呼び出され、mutexのロックが解除されます
スレッド2はmutexをロックし、pthread_cond_signal()
を呼び出します。これにより、mutexがロック解除されます
スレッド1で、pthread_cond_wait()
が呼び出され、再びミューテックスをロックします
スレッド2では、pthread_cond_signal()
が呼び出された後、pthread_mutex_unlock(&mutex)
が実行され、スレッド1によってロックされているミューテックスをロック解除したいようです。私の理解に何か問題がありますか?
その上、同じcond-mutexペアに対してpthread_cond_wait()
を呼び出すことができるスレッドは1つだけであるようにも思えます。しかし、「pthread_cond_signal()関数は、指定された条件変数condでブロックされているスレッドの少なくとも1つをブロック解除する必要があります(condでスレッドがブロックされている場合)」それで、同じcond-mutexペアの多くのスレッドでpthread_cond_wait()
を呼び出すことができるということですか?
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つのスレッドには、ミューテックスがアクセスを保護している共有データ構造があります。最初のスレッドは、ある条件がtrueになるまで待機してから、すぐに何らかの操作を行います(他のスレッドが条件チェックとアクションの間に競合状態を起こさずに条件をfalseにする)。2番目のスレッドは、条件をtrueにするため、それを待っている可能性のある人は誰でもウェイクアップする必要があります。
典型的な例を次に示します。スレッド1は、スレッド2によって満たされる条件を待機しています。
1つのmutexと1つの条件を使用します。
pthread_mutex_t mutex;
pthread_cond_t condition;
スレッド1:
pthread_mutex_lock(&mutex); //mutex lock
while(!condition){
pthread_cond_wait(&condition, &mutex); //wait for the condition
}
/* do what you want */
pthread_mutex_unlock(&mutex);
スレッド2:
pthread_mutex_lock(&mutex);
/* do something that may fulfill the condition */
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&condition); //wake up thread 1
編集
ミューテックスをアトミックに解放し、呼び出しスレッドが条件変数condでブロックするようにします。ここでアトミックとは、「ミューテックスと条件変数への別のスレッドによるアクセスに関してアトミックに」を意味します。