1

考虑以下:

#include <atomic>

std::atomic<unsigned> var;
unsigned foo;
unsigned bar;

unsigned is_this_a_full_fence() {
     var.store(1, std::memory_order_release);
     var.load(std::memory_order_acquire);
     bar = 5;
     return foo;
}

我的想法是 var 的虚拟负载应该防止 foo 和 bar 的后续变量访问在存储之前被重新排序。

代码似乎为重新排序设置了障碍——至少在 x86 上,发布和获取不需要特殊的屏蔽指令。

这是编写完整围栏(LoadStore/StoreStore/StoreLoad/LoadLoad)的有效方法吗?我错过了什么?

我认为该版本创建了 LoadStore 和 StoreStore 障碍。获取创建了一个 LoadStore 和 LoadLoad 屏障。并且两个变量访问之间的依赖关系创建了一个 StoreLoad 屏障?

编辑:将障碍改为全围栏。制作片段 C++。

4

3 回答 3

2

这段代码的一个主要问题是存储和随后加载到同一内存位置显然没有与任何其他线程同步。在 C++ 内存模型中,竞争是未定义的行为,因此编译器可以假设您的代码没有竞争。您的负载可以观察到与存储的值不同的值的唯一方法是进行比赛。因此,在 C++ 内存模型下,编译器可以假设加载遵循存储的值。

这个确切的原子代码序列出现在我的 C++ 标准委员会论文中,没有理智的编译器会在“消除冗余负载”下优化原子。YouTube 上有这篇论文的更长的 CppCon版本。

现在想象一下,C++ 不是一个书呆子,尽管其固有的活泼性质,加载/存储保证会留在那里。现实世界的 ISA 提供了 C++ 所没有的此类保证。您通过获取/释放与其他线程提供了一些发生前的关系,但您没有提供所有线程都同意的唯一总顺序. 所以是的,这将充当围栏,但它与获得顺序一致性,甚至是总商店订单不同。一些架构可能具有以明确定义但不同的顺序观察事件的线程。这对于某些应用程序来说非常好!您需要研究 IRIW(独立读取独立写入)以了解有关此主题的更多信息。x86-TSO 论文在 ad-hoc x86 内存模型的上下文中专门讨论了它,该模型在各种处理器中实现。

于 2018-01-11T05:45:26.180 回答
0

您的伪代码(不是有效的 C++)作为一个整体不是原子的。

例如,存储和加载之间可能发生上下文切换,并且其他一些线程将被调度(或已经在其他一些核心上运行),然后会更改其间的变量。每条机器指令都可能发生上下文切换和中断。

这是编写障碍的有效方法吗

不它不是。另请参见pthread_barrier_init(3p)pthread_barrier_wait(3p)和相关函数。

您应该阅读一些pthread 教程(实际上,C++11 线程是它们之上的一个小抽象)并考虑使用互斥锁。

请注意,这std::memory_order主要影响当前线程(以及它正在观察的内容),并且不要禁止它被中断/上下文切换......

另请参阅此答案

于 2018-01-10T06:13:33.017 回答
0

假设您在多个线程中运行此代码,使用这样的排序是不正确的,因为原子操作不同步(参见下面的链接),因此foo不受bar保护。

但是,查看适用于单个操作的保证仍然可能具有一定的价值。
作为获取操作,不会使用 on和var.load的操作重新排序(线程间)(因此#LoadStore 和#LoadLoad,你是对的)。 但是,, 不受任何重新排序的保护(在此上下文中)。foobar
var.store

#StoreLoad 重新排序可以通过标记两个原子操作来防止seq_cst。在这种情况下,所有线程都将遵守定义的顺序(尽管仍然不正确,因为非原子不受保护)。

EDIT
var.store不受重新排序的保护,因为它作为在它之前排序的操作(即在程序顺序中更早)的单向障碍,并且在您的代码中,在该存储之前没有操作。
var.load充当在它之后排序的操作的单向屏障(即foobar)。

下面是一个基本示例,说明变量 ( foo) 如何由原子存储/加载对保护:

// thread 1
foo = 42;
var.store(1, std::memory_order_release);

// thread 2
while (var.load(std::memory_order_acquire) != 1);
assert(foo == 42);

线程 2 仅观察到线程 1 设置的值后才继续。然后说存储已与加载同步,并且断言无法触发。

有关完整的概述,请查看 Jeff Preshing 的博客文章

于 2018-01-10T09:14:20.367 回答