web-dev-qa-db-ja.com

ブール読み取り/書き込み操作はx86でアトミックではありませんか?

2つのスレッドがあるとします。1つはループ内のブール値を読み取り、もう1つは特定の時間にそれを切り替えることができます。個人的には、C++のsizeof(bool)は1バイトであり、バイトの部分的な読み取り/書き込みは行わないため、これはアトミックである必要があると思いますが、100%確実にしたいです。

それで、はいまたはいいえ?

[〜#〜]編集[〜#〜]

また、将来の参考のために、同じことがintにも当てはまりますか?

28
szx

それはすべて、「アトミック」という言葉が実際に何を意味するかによって異なります。

「最終値は一度に更新されます」(はい、x86ではバイト値が確実に保証されます-少なくとも64ビットまでの正しく整列された値)、または「これをtrueに設定した場合(またはfalse)、設定した後、他のスレッドが別の値を読み取ることはありません」(これはそれほど確実ではありません。これを保証するには、「ロック」プレフィックスが必要です)。

18
Mats Petersson

C++ 11の「アトミック」タイプが対処する3つの別個の問題があります。

  1. ティアリング:読み取りまたは書き込みには複数のバスサイクルが含まれ、操作の途中でスレッドスイッチが発生します。これにより、誤った値が生成される可能性があります。

  2. キャッシュコヒーレンス:1つのスレッドからの書き込みは、そのプロセッサのキャッシュを更新しますが、グローバルメモリは更新しません。別のスレッドからの読み取りはグローバルメモリを読み取り、他のプロセッサのキャッシュに更新された値を表示しません。

  3. コンパイラーの最適化:コンパイラーは、値が別のスレッドからアクセスされないことを前提として、読み取りと書き込みの順序をシャッフルし、混乱を招きます。

std::atomic<bool>を使用すると、これら3つの問題すべてが正しく管理されます。 std::atomic<bool>を使用しないと、せいぜい移植性のないコードで推測できます。

65
Pete Becker

x86は、ワードサイズのワードに合わせた読み取りと書き込みのみを保証します。明示的にアトミックでない限り、他の操作を保証するものではありません。さらに、もちろん、最初に関連する読み取りと書き込みを実際に発行するようにコンパイラーを説得する必要があります。

7
Puppy