状態 (単純な列挙型) を持ち、2 つのスレッドからアクセスされるクラスがあります。状態を変更するには、ミューテックス (boost::mutex) を使用します。状態をチェックするのは安全ですか (たとえば、state_ == ESTABLISHED を比較します)、またはこの場合もミューテックスを使用する必要がありますか? 言い換えれば、別のスレッドによって同時に書き込まれる可能性のある変数を読みたいだけの場合、ミューテックスが必要ですか?
6 に答える
場合によります。
C++ 言語は、スレッドやアトミック性について何も述べていません。
しかし、最近のほとんどの CPU では、整数の読み取りはアトミック操作です。つまり、ミューテックスがなくても、常に一貫した値を読み取ることができます。
ただし、ミューテックスやその他の形式の同期がなければ、コンパイラと CPU は読み取りと書き込みを自由に並べ替えることができるため、より複雑なもの、複数の変数へのアクセスを伴うものは、一般的なケースでは依然として安全ではありません。
書き込みスレッドが一部のデータを更新し、整数フラグを設定してデータが利用可能であることを他のスレッドに通知すると仮定すると、データを更新する前にフラグが設定されるように、これを並べ替えることができます。ミューテックスまたは別の形式のメモリバリアを使用しない限り。
したがって、正しい動作が必要な場合は、ミューテックス自体は必要ありません。また、読み取り中に別のスレッドが変数に書き込みを行っても問題ありません。非常に珍しいCPUで作業していない限り、アトミックになります。ただし、コンパイラまたは CPU での並べ替えを防ぐために、何らかのメモリ バリアが必要です。
2 つのスレッドがあり、それらは情報を交換します。はい、ミューテックスが必要で、おそらく条件付き待機も必要です。
あなたの例では(state_ == ESTABLISHEDと比較してください)、スレッド#2がスレッド#1が接続/状態を開始するのを待っていることを示しています。ミューテックスまたは条件/イベントがない場合、スレッド #2 は継続的にステータスをポーリングする必要があります。
スレッドは、パフォーマンスを向上させる (または応答性を向上させる) ために使用されます。ポーリングは通常、多くの CPU を消費するか、ポーリング間隔によるレイテンシーを導入することにより、パフォーマンスの低下をもたらします。
はい。スレッド b が変数に書き込んでいる間にスレッド a が変数を読み取ると、未定義の値を読み取ることができます。読み取りおよび書き込み操作は、特にマルチプロセッサ システムではアトミックではありません。
一般的に言えば、変数が「volatile」で宣言されている場合はそうではありません。そして、それが単一の変数である場合のみ - それ以外の場合は、レースの可能性について本当に注意する必要があります.
列挙型へのアクセス (読み取りまたは書き込み) は保護する必要があります。
別のこと:スレッドの競合が少なく、スレッドが同じプロセスに属している場合、クリティカルセクションはミューテックスよりも優れています。