C++ 我什么时候真的需要使用 atomic<bool> 而不是 bool?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16320838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When do I really need to use atomic<bool> instead of bool?
提问by Kerrek SB
Isn't atomic<bool>
redundant because bool
is atomic by nature? I don't think it's possible to have a partially modified bool value. When do I really need to use atomic<bool>
instead of bool
?
不是atomic<bool>
多余的,因为bool
本质上是原子的吗?我认为不可能有部分修改的 bool 值。我什么时候真的需要使用atomic<bool>
而不是bool
?
回答by Kerrek SB
Notype in C++ is "atomic by nature" unless it is an std::atomic*
-something. That's because the standard says so.
C++ 中的任何类型都不是“本质上是原子的”,除非它是std::atomic*
-something。那是因为标准是这样说的。
In practice, the actual hardware instructions that are emitted to manipulate an std::atomic<bool>
may (or may not) be the same as those for an ordinary bool
, but being atomic is a larger concept with wider ramifications (e.g. restrictions on compiler re-ordering). Furthermore, some operations (like negation) are overloaded on the atomic operation to create a distinctly different instruction on the hardware than the native, non-atomic read-modify-write sequence of a non-atomic variable.
在实践中,发出来操作 an 的实际硬件指令std::atomic<bool>
可能(也可能不同)与普通 的相同bool
,但原子性是一个更大的概念,具有更广泛的影响(例如对编译器重新排序的限制)。此外,某些操作(如否定)在原子操作上重载,以在硬件上创建与非原子变量的本机、非原子读-修改-写序列截然不同的指令。
回答by Dims
Remember about memory barriers. Although it may be impossible to change bool
partially, it is possible that multiprocessor system has this variable in multiple copies and one thread can see old value even after another thread has changed it to new. Atomic introduces memory barrier, so it becomes impossible.
记住内存障碍。尽管bool
部分更改可能是不可能的,但多处理器系统可能会将这个变量复制到多个副本中,即使在另一个线程将其更改为新值之后,一个线程仍可以看到旧值。Atomic 引入了内存屏障,因此变得不可能。
回答by Pete Becker
C++'s atomic types deal with threepotential problems. First, a read or write can be torn by a task switch if the operation requires more than one bus operation (and that canhappen to a bool
, depending on how it's implemented). Second, a read or write may affect only the cache associated with the processor that's doing the operation, and other processors may have a different value in their cache. Third, the compiler can rearrange the order of operations if they don't affect the result (the constraints are a bit more complicated, but that's sufficient for now).
C++ 的原子类型处理三个潜在的问题。首先,如果操作需要多个总线操作(这可能发生在 a 上bool
,取决于它的实现方式),则任务切换可能会破坏读取或写入。其次,读取或写入可能仅影响与执行操作的处理器相关联的缓存,而其他处理器在其缓存中可能具有不同的值。第三,如果不影响结果,编译器可以重新排列操作顺序(约束有点复杂,但现在已经足够了)。
You can deal with each of these three problems on your own by making assumptions about how the types you are using are implemented, by explicitly flushing caches, and by using compiler-specific options to prevent reordering (and, no, volatile
doesn't do this unless your compiler documentation says it does).
您可以自己处理这三个问题中的每一个,方法是假设您正在使用的类型是如何实现的,通过显式刷新缓存,以及使用特定于编译器的选项来防止重新排序(并且,不,volatile
不这样做除非您的编译器文档说它确实如此)。
But why go through all that? atomic
takes care of it for you, and probably does a better job than you can do on your own.
但为什么要经历这一切?atomic
为您照顾它,并且可能比您自己做的更好。
回答by Andrew Tomazos
Consider a compare and exchange operation:
考虑比较和交换操作:
bool a = ...;
bool b = ...;
if (a)
swap(a,b);
After we read a, we get true, another thread could come along and set a false, we then swap (a,b), so after exit b is false, even though the swap was made.
在我们读取 a 后,我们得到 true,另一个线程可能会出现并设置 false,然后我们交换 (a,b),因此在退出后 b 为 false,即使进行了交换。
Using std::atomic::compare_exchange
we can do the entire if/swap logic atomicallysuch that the other thread could not set a to false in between the if and the swap (without locking). In such a circumstance if the swap was made than b must be false on exit.
使用std::atomic::compare_exchange
我们可以原子地完成整个 if/swap 逻辑,这样另一个线程就不能在 if 和交换之间将 a 设置为 false(没有锁定)。在这种情况下,如果进行了交换,那么 b 在退出时必须为假。
This is just one example of an atomic operation that applies to a two value type such as bool.
这只是适用于双值类型(例如 bool)的原子操作的一个示例。
回答by huskerchad
Atomic operations are about more than just torn values, so while I agree with you and other posters that I am not aware of an environment where torn bool
is a possibility, there is more at stake.
原子操作不仅仅是撕裂的价值,所以虽然我同意你和其他海报,我不知道撕裂bool
是可能的环境,但还有更多的危险。
Herb Sutter gave a great talk about this which you can view online. Be warned, it is a long and involved talk. Herb Sutter, Atomic Weapons. The issue boils down to avoiding data races because it allows you to have the illusion of sequential consistency.
Herb Sutter 对此进行了精彩的演讲,您可以在线查看。请注意,这是一个漫长而复杂的谈话。赫伯·萨特,原子武器。问题归结为避免数据竞争,因为它让您产生顺序一致性的错觉。
回答by Alexander Shukaev
Atomicity of certain types depends exclusively on the underlying hardware. Each processor architecture has different guarantees about atomicity of certain operations. For example:
某些类型的原子性完全取决于底层硬件。每个处理器体系结构对某些操作的原子性有不同的保证。例如:
The Intel486 processor (and newer processors since) guarantees that the following basic memory operations will always be carried out atomically:
- Reading or writing a byte
- Reading or writing a word aligned on a 16-bit boundary
- Reading or writing a doubleword aligned on a 32-bit boundary
Intel486 处理器(以及之后的更新处理器)保证以下基本内存操作将始终以原子方式执行:
- 读取或写入一个字节
- 读取或写入在 16 位边界上对齐的字
- 读取或写入在 32 位边界上对齐的双字
Other architectures have different specifications on which operations are atomic.
其他架构对哪些操作是原子的有不同的规范。
C++ is a high-level programming language that strives to abstract you from the underlying hardware. For this reason standard simply cannot permit one to rely on such low-level assumptions because otherwise your application wouldn't be portable. Accordingly, all the primitive types in C++ are provided with atomic
counterparts by C++11 compliant standard library out-of-the-box.
C++ 是一种高级编程语言,它致力于将您从底层硬件中抽象出来。出于这个原因,标准根本不允许人们依赖这种低级假设,否则您的应用程序将无法移植。因此,C++ 中的所有原始类型atomic
都由 C++11 兼容的标准库开箱即用地提供了对应物。