4

条件変数は通常、参照する状態がミューテックスの下で変更されるように使用されます。ただし、状態が 1 つのセットのみのフラグである場合、同時実行を防ぐためにミューテックスは必要ありません。したがって、次のようなことをしたいかもしれません:

flag = 1;
pthread_cond_broadcast(&cvar);

pthread_cond_broadcastただし、これは書き込みメモリ バリアを意味する場合にのみ安全です。そうしないと、待機中のスレッドは、フラグが書き込まれる前に条件変数のブロードキャストが表示される可能性があります。つまり、待機中のスレッドが目覚め、cvar シグナルを消費する可能性がありますが、まだフラグが表示されます0

だから、私の質問は次のとおりです。pthread_cond_broadcastandpthread_cond_signal呼び出しは、書き込みメモリバリアを意味しますか? もしそうなら、これは関連する POSIX (または他の) 仕様のどこで指定されていますか? この点については、仕様が不明確なようでした。

注: 実際には、これによりメモリ バリアが発生することは承知しています (Linux では、スレッドの起動は完全な CPU メモリ バリアを意味し、クロス ライブラリ関数呼び出しはコンパイラのメモリ バリアを意味するため)。しかし、私はここでスペックが保証するものに興味があります。

4

3 に答える 3

9

メモリ バリアを意味するかどうかに関係なく、コードはまだ正しくありません。読み取り側を考えてみましょう:

while (flag == 0)
    pthread_cond_wait(&cvar, &mutex);

読み取り側がflag == 0待機のテストと実行の間で中断されている場合、書き込み側はflag = 1; pthread_cond_signal(&cvar);. 読み取り側はウェイクアップを完全に見逃します - それは永遠に待ちます。ウェイクアップはキューに入れられないことに注意してください。条件変数がシグナル状態になったときにウェイターが存在しない場合、シグナルは効果がありません。これを回避するには、とにかく書き込み側でミューテックスをロックする必要があります。

于 2011-08-30T12:22:20.193 に答える
3

POSIXでは、あるスレッドから変数に書き込み、別のスレッドから変数を読み取る場合は、ミューテックスで変数を保護する必要があります。の例外はありませんpthread_cond_broadcast

プラットフォーム/コンパイラがアトミック変数を提供している場合、それらはそれらについて追加の保証を行う可能性があります。たとえば、flagがC ++ 11のstd::atomic<int>場合、このコードは問題ありません。

于 2011-08-30T11:19:06.223 に答える