默认情况下,我可以阅读或修改或原子地比较哪些类型? 或者我应该为所有操作显式使用所有类型的原子操作吗?
答案 0 :(得分:1)
是的,如果你需要原子性,你应该总是使用原子类型或原子操作。从来没有什么不同。
形式上,默认情况下,非原子类型不提供任何类型的原子访问。实际上,对于当前的CPU,任何内置类型都可以原子方式读写(但不能修改)。但是,这不是你有保证的东西,绝对不是你应该依赖的东西。这只是一个实施细节 当前CPU上的所有读取和写入都通过缓存。只能从主存储器读取完整的高速缓存行(通常大约64-128字节)或写回,高速缓存行是最大内置类型大小的倍数。这意味着如果一个类型正确对齐,它必然包含在一个缓存行中,这会自动使其读取或写入原子。但是,修改值是一个读 - 修改 - 写操作,这意味着即使每个步骤都是原子的,整个操作也不是。
原子性不仅仅是能够原子地读取(或修改)一个值,例如,您可能需要正确的排序保证。即使读取和写入是原子的,如果不同处理器按照您预期的顺序看不到修改,您的代码将无法正常工作。编译器和CPU(在一些合理的限制范围内)允许重新排序指令,包括加载和存储。但是,这可能意味着您的代码无法正确执行。
原子操作因此具有记忆模型"与它们相关联,它允许您提供有关在线程之间以及相关或不相关数据之间需要保证的事件的其他信息。有关每种模式的详细说明,请参阅GCC Wiki
默认情况下,原子操作选择顺序一致的模型,这是最安全的模式,具有最严格的限制。如果您知道不需要某些保证,则可以选择不同的模型,这可能(或可能不是,取决于体系结构)导致生成更高性能的代码。
内存模型的优点在于它们将实现细节,架构特性和编译器voodoo抽象为描述算法要求的形式,并保证满足这些要求。
通常,编译器将能够使用普通的非原子机器指令并仍然保证满足您的要求(可能必须放弃一个或另一个重新排序)。这取决于目标硬件如何工作的实际细节以及您需要的保证 总而言之,原子和内存模型的使用不仅更加舒适,而且比在低级别(内联汇编程序)上手动进行拙劣操作更容易出现故障,它也可能是最高效的方法。
答案 1 :(得分:0)
查看http://en.cppreference.com/w/cpp/atomic/atomic。
提及std::atomic<T>
,就像其中一条评论中提到的@IgorTandetnik一样。