web-dev-qa-db-ja.com

読み取りにミューテックスが必要ですか?

状態(単純な列挙型)があり、2つのスレッドからアクセスされるクラスがあります。状態を変更するには、ミューテックス(boost :: mutex)を使用します。状態を確認しても安全ですか(たとえば、state_ == ESTABLISHEDを比較)、この場合もミューテックスを使用する必要がありますか?言い換えると、別のスレッドによって同時に書き込まれる可能性のある変数を読み取りたいだけの場合、ミューテックスが必要ですか?

42
Tom

場合によります。

C++言語は、スレッドや原子性については何も述べていません。

しかし、most最近のCPUでは、整数の読み取りはアトミック操作です。つまり、ミューテックスがなくても、常に一貫した値を読み取ります。

ただし、ミューテックス、またはその他の形式の同期がなければ、コンパイラとCPUは読み取りと書き込みを自由に並べ替えることができるため、より複雑なもの、複数の変数へのアクセスを含むものは、一般的なケースでは依然として安全ではありません。 。

ライタースレッドが一部のデータを更新し、データが利用可能であることを他のスレッドに通知するために整数フラグを設定すると仮定すると、フラグがbeforeデータの更新。 mutexまたは別の形式のメモリバリアを使用しない限り。

したがって、正しい動作が必要な場合は、そのようなミューテックスは必要ありません。また、読み取り中に別のスレッドが変数に書き込んでも問題はありません。非常に珍しいCPUで作業しているのでない限り、アトミックです。しかしdoコンパイラまたはCPUでの並べ替えを防ぐために、何らかのメモリバリアが必要です。

19
jalf

2つのスレッドがあり、それらは情報を交換します。はい、ミューテックスが必要で、おそらく条件付き待機も必要です。

あなたの例では(state_ == ESTABLISHEDと比較)、スレッド#2がスレッド#1が接続/状態を開始するのを待っていることを示しています。ミューテックスまたは条件/イベントがない場合、スレッド#2はステータスを継続的にポーリングする必要があります。

スレッドは、パフォーマンスを向上させる(または応答性を向上させる)ために使用され、ポーリングは通常、CPUを大量に消費するか、ポーリング間隔による遅延を導入することによって、パフォーマンスの低下を招きます。

9
Ernelli

実際には、読み取りのためにオブジェクトへのアクセスをロックする理由はありません。書き込み中はロックするだけです。これがまさに、リーダー/ライターロックです。書き込み操作がない限り、オブジェクトをロックしません。パフォーマンスが向上し、デッドロックが防止されます。より詳細な説明については、次のリンクを参照してください。

wikipediacodeproject

2
geva30

はい。スレッドbが変数を書き込んでいる間にスレッドaが変数を読み取る場合、未定義の値を読み取ることができます。特にマルチプロセッサシステムでは、読み取りおよび書き込み操作はアトミックではありません。

2
Jeff Ober

変数が「volatile」で宣言されている場合は、一般的にそうしません。そして、それが単一の変数である場合のみ-それ以外の場合は、可能なレースについて本当に注意する必要があります。

1
EFraim

Enumへのアクセス(読み取りまたは書き込み)は保護する必要があります。

もう1つ:スレッドの競合が少なく、スレッドが同じプロセスに属している場合、クリティカルセクションはミューテックスよりも優れています。

0
aJ.