web-dev-qa-db-ja.com

mutexをロックせずにpthread_cond_signalを呼び出す

pthread_cond_signalを呼び出す前にmutexをロックし、呼び出し後にmutextのロックを解除する必要があることをどこかで読みました。

Pthread_cond_signal()ルーチンは、条件変数を待機している別のスレッドにシグナルを送る(またはウェイクアップする)ために使用されます。 mutexがロックされた後に呼び出す必要があり、pthread_cond_wait()ルーチンを完了するためにmutexをロック解除する必要があります。

私の質問は:mutexをロックせずにpthread_cond_signalまたはpthread_cond_broadcastメソッドを呼び出しても大丈夫ではないですか?

77
Meysam

条件と信号を変更するコードパスでミューテックスをロックしないと、ウェイクアップを失う可能性があります。このプロセスのペアを検討してください。

プロセスA:

_pthread_mutex_lock(&mutex);
while (condition == FALSE)
    pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
_

プロセスB(不正解):

_condition = TRUE;
pthread_cond_signal(&cond);
_

次に、conditionFALSEで始まる命令の可能性のあるインターリーブを検討します。

_Process A                             Process B

pthread_mutex_lock(&mutex);
while (condition == FALSE)

                                      condition = TRUE;
                                      pthread_cond_signal(&cond);

pthread_cond_wait(&cond, &mutex);
_

conditionTRUEになりましたが、プロセスAは条件変数を待機し続けています-ウェイクアップ信号を逃しました。プロセスBを変更してミューテックスをロックする場合:

プロセスB(正しい):

_pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
_

...その場合、上記は発生しません。ウェイクアップを見逃すことはありません。

(あなたはcanが実際にpthread_cond_signal()pthread_mutex_unlock()の後に移動することに注意してください。スレッドの最適なスケジューリング、および条件自体の変更により、このコードパスですでにミューテックスをロックしている必要があります)。

134
caf

このマニュアルによると:

pthread_cond_broadcast()またはpthread_cond_signal()関数は、現在mutexを所有しているかどうかにかかわらず、スレッドによって呼び出されます。 pthread_cond_wait()またはpthread_cond_timedwait()を呼び出すスレッドは、待機中に条件変数に関連付けられています。ただし、予測可能なスケジューリング動作が必要な場合、そのミューテックスはpthread_cond_broadcast()またはpthread_cond_signal()を呼び出すスレッドによってロックされます。

予測可能なスケジューリング動作ステートメントの意味は、comp.programming.threadsのDave Butenhof( Programming with POSIX Threads の著者)によって説明されており、利用可能です- ここ

46
icecrime

サンプルコードのcafは、最初にミューテックスをロックせずにconditionを変更します。プロセスBがその変更中に単にmutexをロックし、pthread_cond_signalを呼び出す前にmutexをまだロック解除した場合、問題はありません---それについて正しいですか?

私は直感的に、cafのpositionが正しいと信じています。mutexロックを所有せずにpthread_cond_signalを呼び出すのは悪い考えです。しかし、cafのは、実際にはこの位置を支持する証拠ではありません。ミューテックスを最初にロックしていない限り、ミューテックスによって保護されている共有状態を変更するのは悪い考えであるという、はるかに弱い(実際には自明の)立場を裏付ける証拠にすぎません。

pthread_cond_signalに続いてpthread_mutex_unlockを呼び出すと正しい動作が得られるが、pthread_mutex_unlockに続いてpthread_cond_signalを呼び出すと正しくない動作をするサンプルコードを提供できますか?

4
Quuxplusone