C ++ 11中的内存排序与主内存刷新顺序有关吗?

jed*_*dib 6 c++ atomic memory-model memory-barriers stdatomic

我不确定我是否完全理解C ++ 11中原子性和内存排序的概念(我可能全都错了)。让我们以这个简单的单线程示例为例:

int main()
{
    std::atomic<int> a(0);
    std::atomic<int> b(0);
    a.store(16);
    b.store(10);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在此单线程代码中,如果a和b不是原子类型,则编译器可能以某种方式对指令进行了重新排序,例如,在汇编代码中,例如,我有一条将10赋给'b'的move指令,然后将将16分配给“ a”。因此,对我来说,作为原子变量,它可以确保我在源代码中声明的“ b移动指令”之前拥有“移动指令”。之后,处理器将带有执行单元,预取指令以及乱序框。无论汇编代码中的指令顺序如何,该处理器都可以在“ a指令”之前处理“ b指令”。

以我的理解,这就是内存排序模型出现的地方。从那时起,如果我让默认模型顺序一致。一个可以保证我清除主内存中的这些值(10和16)将遵守我在源代码中存储的顺序。这样,处理器将开始清空寄存器或高速缓存,其中将16存储到主存储器中以进行更新'a',然后处理器将清空主存储器中的10'b'。

这样的行为的确使我了解到,如果我使用宽松的内存模型。只有最后一部分不能保证,因此主内存中的刷新可能完全混乱。

抱歉,如果您在阅读我时遇到麻烦,我的英语仍然很差。但是谢谢你们的时间。

Seb*_*edl 4

C++ 内存模型是关于抽象机器和值可见性,而不是关于“主内存”、“写入队列”或“刷新”等具体事物。

在您的示例中,内存模型指出,由于写入a发生在写入之前b,因此任何从 读取 10 的线程都b必须在随后从 读取时a看到 16(当然,除非此后已被覆盖)。

这里重要的是建立事前关系和价值可见性。如何映射到缓存和内存取决于编译器。在我看来,最好停留在抽象级别上,而不是尝试将模型映射到您对硬件的理解,因为

  • 您对硬件的理解可能是错误的。硬件比 C++ 内存模型还要复杂。
  • 即使您现在的理解是正确的,更高版本的硬件也可能有不同的模型,至少在子系统中是这样。
  • 通过映射到硬件模型,您可能会对不同硬件模型的影响做出错误的假设。例如,如果您了解内存模型如何映射到 x86 硬件,您将无法理解 PowerPC 上消耗和获取之间的细微差别。
  • C++ 模型非常适合推理正确性。