Edi*_*tis 1 c++ atomic c++11 stdatomic
原子是否将可重复读取缓存在寄存器中?或者它们只是原子的,即读取可能不会分成多个部分?
MSVC++、clang++ / clang-cl 和 g++ 不会在没有内存排序的情况下缓存原子读取:
#include <atomic>
using namespace std;
int x( atomic_int const &ai )
{
int
a = ai.load( memory_order_relaxed ),
b = ai.load( memory_order_relaxed );
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
克++:
movl (%rdi), %edx
movl (%rdi), %eax
addl %edx, %eax
ret
Run Code Online (Sandbox Code Playgroud)
铿锵-cl:
mov eax, dword ptr [rcx]
add eax, dword ptr [rcx]
ret
Run Code Online (Sandbox Code Playgroud)
CL:
mov edx, DWORD PTR [rcx]
mov eax, DWORD PTR [rcx]
add eax, edx
ret 0`
Run Code Online (Sandbox Code Playgroud)
我认为目前还没有编译器真正进行特定的优化。在许多情况下,程序员不太可能想要这种行为,因为他们希望来自其他线程的存储尽快变得可见。
我认为这是编译器在对原子应用优化时非常保守的部分原因,尤其是那些会消除加载/存储的优化,尽管我认为在您的特定示例中应用优化没有任何问题。
然而,从 ISO C++ 标准的角度来看,编译器将被允许将读取缓存在寄存器中并通常重用它。
编译器只需确保另一个线程对原子变量的写入在有限时间内对该线程可见,即读取原子的无限循环不应继续读取缓存的寄存器值。
它还应该使它们在“合理的时间内”可见([atomics.order]/11)。这取决于您如何准确地解释“合理”来确定这种缓存可以达到什么程度。
另请注意,原子不仅仅是保证所有线程都以原子方式进行读取和写入。即使只有std::memory_order_relaxed(最弱的变体)操作,它也保证所有线程都同意一个全局修改顺序,其中写入原子发生,这与每个单独线程中的排序一致,并且发生读-修改-写操作原子地并且与该顺序一致。对于非原子对象,不能保证这一点。
通过其他std::memory_order_*选项(默认),操作还提供除单个原子对象本身之外的其他对象的内存排序保证。