ミューテックスをロックせずにpthread_cond_signalを呼び出す


82

pthread_cond_signalを呼び出す前にミューテックスをロックし、呼び出した後にミューテキストのロックを解除する必要があることをどこかで読みました。

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

私の質問は、ミューテックスをロックせずにpthread_cond_signalまたはpthread_cond_broadcastメソッドを呼び出しても大丈夫ではないかということです。

回答:


140

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

プロセスA:

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

プロセスB(不正解):

condition = TRUE;
pthread_cond_signal(&cond);

次に、命令のこの可能なインターリーブを検討します。ここで、次のようにcondition始まりますFALSE

Process A                             Process B

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

                                      condition = TRUE;
                                      pthread_cond_signal(&cond);

pthread_cond_wait(&cond, &mutex);

condition今でTRUEはなく、プロセスAは、条件変数にこだわって待っている-それは、ウェイクアップ信号を逃しました。プロセスBを変更してミューテックスをロックする場合:

プロセスB(正しい):

pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

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

(実際には、の後に自分自身を移動できます、これによりスレッドのスケジューリングが最適化されなくなる可能性があり、条件自体を変更するため、このコードパスにすでにあるミューテックスをロックする必要があります)。pthread_cond_signal()pthread_mutex_unlock()


3
@Nemo:はい、「正しい」パスでは、ミューテックスのロック解除後に移動pthread_signal_cond() できますが、移動しない方がよいでしょう。呼び出している時点でpthread_signal_cond()、条件自体を変更するためにミューテックスをロックする必要があると言った方が正しいかもしれません。
caf 2011年

@Nemo:はい、コードが壊れているため、「正しくない」とマークされています。この質問をしている人は、シグナリングパスで完全にロックアウトすることを検討していることがよくあります。おそらくあなたの経験は異なります。
caf 2011年

8
価値があるのは、信号の前または後にロックを解除するかどうかの問題は、実際には答えるのが簡単ではないようです。後でロックを解除すると、優先度の低いスレッドが優先度の高いスレッドからイベントを盗むことができなくなりますが、優先度を使用していない場合は、シグナルの前にロックを解除すると、実際にシステムコール/コンテキストスイッチの数が減ります。全体的なパフォーマンスを向上させます。
R .. GitHub STOP HELPING ICE 2011

1
@R ..あなたはそれを後方に持っています。信号の前にロックを解除すると、システムコールの数が増え、全体的なパフォーマンスが低下します。ロック解除の前にシグナルを送信すると、実装はシグナルがスレッドをウェイクアップできない可能性があることを認識し(cvでブロックされたスレッドは前進するためにミューテックスを必要とするため)、高速パスを使用できるようにします。ロック解除後にシグナルを送信すると、ロック解除とシグナルの両方がスレッドをウェイクアップする可能性があります。つまり、どちらもコストのかかる操作です。
デビッドシュワルツ

1
@Alceste_:POSIXのこのテキストを参照してください:"スレッドが条件変数を待機し、pthread_cond_timedwait()またはpthread_cond_wait()操作のいずれかに特定のミューテックスを指定すると、そのミューテックスと条件変数の間に動的バインディングが形成され、少なくとも1つのスレッドが条件変数でブロックされています。この間、スレッドが別のミューテックスを使用してその条件変数を待機しようとした場合の影響は定義されていません。 "
caf 2018

48

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

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

予測可能なスケジューリング動作ステートメントの意味は、comp.programming.threadsでDave Butenhof(POSIXスレッドを使用したプログラミングの作成者)によって説明されており、ここから入手できます


6
DaveButenhofからのメールをリンクするための+1。私はいつもこの問題について自分で疑問に思っていました、今私は知っています...今日重要なことを学びました。ありがとう。
Nils Pipenbrinck 2010

予測可能なスケジューリング動作が必要な場合は、ステートメントを必要な順序で1つのスレッドに配置するか、スレッドの優先順位を使用します。
カズ2013年

7

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

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

呼び出しのpthread_cond_signal後にpthread_mutex_unlock正しい動作が得られるが、呼び出しのpthread_mutex_unlock後にpthread_cond_signal誤った動作が生じるサンプルコードを誰かが提供できますか?


3
実は、私は私の質問はの複製であると考え、この1、そして答えは「それの罰金です、あなたがすることができ、完全に何の正当性の問題はありません。ミューテックスのロックを所有することなく、pthread_cond_signalを呼んでいます。しかし、一般的な実装では、あなたが巧妙な最適化を逃しますpthreadの奥深くにあるため、ロックを保持したままpthread_cond_signalを呼び出すことをお勧めします。」
quuxplusone 2012年

私は私の答えの最後の段落でこの観察をしました。
caf 2013年

ここに良いシナリオがあります:stackoverflow.com/a/6419626/1284631動作が正しくないとは主張しておらず、動作が期待どおりでない可能性がある場合のみを示していることに注意してください。
user1284631 2014年

呼び出し場所サンプルコードを作成することが可能であるpthread_cond_signal後にpthread_mutex_unlock信号が述語の変化を見た後にブロックされた「間違っている」スレッド、一つでキャッチされているため、失われたウェイクアップにつながることができます。これは、同じ条件変数を複数の述語に使用できpthread_cond_broadcast、とにかくまれで壊れやすいパターンであるを使用しない場合にのみ問題になります。
デビッドシュワルツ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.