gpt4 book ai didi

c++ - C++ 内存模型中的哪些确切规则可以防止在获取操作之前重新排序?

转载 作者:IT老高 更新时间:2023-10-28 22:13:42 26 4
gpt4 key购买 nike

我对以下代码中的操作顺序有疑问:

std::atomic<int> x;
std::atomic<int> y;
int r1;
int r2;
void thread1() {
y.exchange(1, std::memory_order_acq_rel);
r1 = x.load(std::memory_order_relaxed);
}
void thread2() {
x.exchange(1, std::memory_order_acq_rel);
r2 = y.load(std::memory_order_relaxed);
}

鉴于 cppreference 页面 (https://en.cppreference.com/w/cpp/atomic/memory_order) 上对 std::memory_order_acquire 的描述,

A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load.

似乎很明显,在同时运行 thread1thread2 之后永远不会有 r1 == 0 && r2 == 0 的结果.

但是,我在 C++ 标准中找不到任何措辞(目前正在查看 C++14 草案),该标准确保两个宽松的加载不能通过获取-发布交换重新排序。我错过了什么?

编辑:正如评论中所建议的,实际上可以使 r1 和 r2 都等于 0。我已将程序更新为使用 load-acquire,如下所示:

std::atomic<int> x;
std::atomic<int> y;
int r1;
int r2;
void thread1() {
y.exchange(1, std::memory_order_acq_rel);
r1 = x.load(std::memory_order_acquire);
}
void thread2() {
x.exchange(1, std::memory_order_acq_rel);
r2 = y.load(std::memory_order_acquire);
}

现在可以同时执行 thread1thread2r1r2 都等于 0 >?如果不是,哪些 C++ 规则可以防止这种情况发生?

最佳答案

该标准没有根据操作如何围绕具有特定排序参数的原子操作进行排序来定义 C++ 内存模型。相反,对于获取/释放排序模型,它定义了诸如“同步”和“发生前”之类的正式关系,用于指定数据如何在线程之间同步。

N4762,§29.4.2 - [atomics.order]

An atomic operation A that performs a release operation on an atomic object M synchronizes with an atomic operation B that performs an acquire operation on M and takes its value from any side effect in the release sequence headed by A.

在第 6.8.2.1-9 节中,该标准还规定,如果存储 A 与加载 B 同步,则任何在 A 之前排序的线程间“发生之前”任何在 B 之后排序的内容。

在您的第二个示例(第一个甚至更弱)中没有建立“同步与”(因此线程间发生之前)关系,因为缺少运行时关系(检查负载的返回值)。
但即使您确实检查了返回值,它也无济于事,因为 exchange 操作实际上并没有“释放”任何东西(即在这些操作之前没有对内存操作进行排序)。原子加载操作不会“获取”任何内容,因为加载后没有任何操作被排序。

因此,根据标准,两个示例中载荷的四种可能结果(包括 0 0)中的每一种都是有效的。事实上,标准给出的保证在所有操作上都不比memory_order_relaxed强。

如果要在代码中排除 0 0 结果,则所有 4 个操作都必须使用 std::memory_order_seq_cst。这保证了所涉及操作的单一总顺序。

关于c++ - C++ 内存模型中的哪些确切规则可以防止在获取操作之前重新排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52606524/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com