web-dev-qa-db-ja.com

boolの代わりにatomic <bool>を本当に使用する必要があるのはいつですか?

boolは本質的にアトミックであるため、atomic<bool>は冗長ではありませんか?部分的に変更されたブール値を持つことは不可能だと思います。いつboolの代わりにatomic<bool>を使用する必要があるのですか?

75
user955249

No C++の型は、std::atomic*- somethingでない限り、「本質的にアトミック」です。それは標準がそう言っているからです。

実際には、std::atomic<bool>を操作するために発行される実際のハードウェア命令は、通常のboolの命令と同じかもしれません(そうでないかもしれません)たとえば、コンパイラの並べ替えの制限)。さらに、一部の操作(否定など)はアトミック操作でオーバーロードされ、非アトミック変数のネイティブの非アトミック読み取り-変更-書き込みシーケンスとは明らかに異なる命令をハードウェア上に作成します。

84
Kerrek SB

メモリバリア について覚えておいてください。 boolを部分的に変更することは不可能かもしれませんが、マルチプロセッサシステムではこの変数が複数のコピーにあり、別のスレッドが新しい値に変更した後でも、1つのスレッドが古い値を見ることができます。 Atomicはメモリバリアを導入するため、不可能になります。

60
Dims

C++のアトミックタイプは、three潜在的な問題を処理します。まず、操作に複数のバス操作が必要な場合、タスクスイッチによって読み取りまたは書き込みが破損する可能性があります(実装方法に応じてboolcanが発生します)。第二に、読み取りまたは書き込みは、操作を実行しているプロセッサに関連付けられたキャッシュにのみ影響を与える可能性があり、他のプロセッサのキャッシュには異なる値が含まれる場合があります。第三に、結果に影響を与えない場合、コンパイラーは操作の順序を並べ替えることができます(制約はもう少し複雑ですが、今のところはそれで十分です)。

使用している型がどのように実装されているかを仮定し、明示的にキャッシュをフラッシュし、コンパイラー固有のオプションを使用して並べ替えを防ぐことで、これら3つの問題をそれぞれ独自に処理できます(そして、volatileは、コンパイラのドキュメントに記載がない限り、これを行いません)。

しかし、なぜすべてを通過するのですか? atomicはあなたのためにそれを処理し、おそらくあなた自身でできるよりも良い仕事をします。

22
Pete Becker

アトミック操作は単なる破れた値以上のものであるため、破れたboolが可能性のある環境については知らないというあなたと他のポスターに同意しますが、さらに危険にさらされています。

ハーブサッターはこれについて素晴らしい講演を行い、オンラインで見ることができます。注意してください、それは長くて複雑な話です。 ハーブサッター、原子兵器 。この問題は、データの競合を回避することに要約されます。これにより、シーケンシャルな一貫性の錯覚を抱くことができるためです。

18
huskerchad

比較および交換操作を検討してください。

bool a = ...;
bool b = ...;

if (a)
    swap(a,b);

Aを読み取った後、trueになり、別のスレッドが現れてfalseを設定する可能性があるため、(a、b)をスワップするため、exit bがfalseになった後、たとえスワップが行われたとしても。

std::atomic::compare_exchangeを使用して、if/swapロジック全体を行うことができますアトミックに ifとswapの間で他のスレッドがfalseに設定できません(ロックなし)。このような状況では、スワップが行われた場合、bは終了時にfalseでなければなりません。

これは、boolなどの2つの値型に適用されるアトミック操作のほんの一例です。

16
Andrew Tomazos

特定のタイプのアトミック性は、基礎となるハードウェアのみに依存します。各プロセッサアーキテクチャには、特定の操作の原子性に関するさまざまな保証があります。例えば:

Intel486プロセッサ(およびそれ以降の新しいプロセッサ)は、次の基本的なメモリ操作が常にアトミックに実行されることを保証します。

  • バイトの読み取りまたは書き込み
  • 16ビット境界に整列されたWordの読み取りまたは書き込み
  • 32ビット境界に位置合わせされたダブルワードの読み取りまたは書き込み

他のアーキテクチャには、操作がアトミックである異なる仕様があります。

C++は、基礎となるハードウェアからあなたを引き離そうとする高レベルのプログラミング言語です。このため、標準では、そのような低レベルの仮定に依存することを単に許可することはできません。したがって、C++のすべてのプリミティブ型には、すぐに使用可能なC++ 11準拠の標準ライブラリにより、対応するatomicが提供されます。

8