gpt4 book ai didi

c++ - C++ memory_order_acquire/release问题

转载 作者:行者123 更新时间:2023-12-02 10:11:10 24 4
gpt4 key购买 nike

我最近了解了c++的六个内存顺序,我对memory_order_acquirememory_order_release感到非常困惑,这是cpp的示例:

#include <thread>
#include <atomic>
#include <cassert>

std::atomic<bool> x = {false};
std::atomic<bool> y = {false};
std::atomic<int> z = {0};

void write_x() { x.store(true, std::memory_order_seq_cst); }
void write_y() { y.store(true, std::memory_order_seq_cst); }

void read_x_then_y() {
while (!x.load(std::memory_order_seq_cst));

if (y.load(std::memory_order_seq_cst))
++z;
}

void read_y_then_x() {
while (!y.load(std::memory_order_seq_cst));

if (x.load(std::memory_order_seq_cst))
++z;
}

int main() {
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);

a.join(); b.join(); c.join(); d.join();

assert(z.load() != 0); // will never happen
}
在cpp引用页中,它说:

This example demonstrates a situation where sequential ordering is necessary.

Any other ordering may trigger the assert because it would be possiblefor the threads c and d to observe changes to the atomics x and y inopposite order.


所以我的问题是,为什么在这里不能使用 memory_order_acquire memory_order_release ? memory_order_acquire和memory_order_release提供什么语义?
一些引用:
https://en.cppreference.com/w/cpp/atomic/memory_order
https://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync

最佳答案

顺序一致性提供所有顺序一致操作的单个总顺序。因此,如果您在线程A中有一个顺序一致的存储,而在线程B中有一个顺序一致的加载,并且存储在加载之前被排序(按照所述单个总顺序),那么B会观察到A所存储的值。保证存储对其他线程“直接可见”。发行商店不提供此保证。
正如彼得·科德斯(Peter Cordes)正确指出的那样,“立即可见”一词相当不精确。 “可见性”源于以下事实:所有seq-cst操作都是完全有序的,并且所有线程都遵守该顺序。由于存储和加载是完全有序的,因此在执行后续加载(按单个总顺序)之前,存储的值变得可见。
在不同线程中的获取/释放操作之间不存在这种总顺序,因此无法保证可见性。仅当获取操作观察到释放操作的值后,才对操作进行排序,但是无法保证何时释放操作的值对执行获取操作的线程可见。
让我们考虑一下在此示例中使用acquire / release会发生什么:

void write_x() { x.store(true, std::memory_order_release); }
void write_y() { y.store(true, std::memory_order_release); }

void read_x_then_y() {
while (!x.load(std::memory_order_acquire));

if (y.load(std::memory_order_acquire))
++z;
}

void read_y_then_x() {
while (!y.load(std::memory_order_acquire));

if (x.load(std::memory_order_acquire))
++z;
}

int main() {
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);

a.join(); b.join(); c.join(); d.join();

assert(z.load() != 0); // can actually happen!!
}
由于我们无法保证可见性,因此线程 c可以观察到 x == truey == false,而线程 d可以同时观察到 y == truex == false。因此,两个线程都不会增加 z,并且断言将触发。
有关C++内存模型的更多详细信息,我可以推荐我与他人合着的这篇论文: Memory Models for C/C++ Programmers

关于c++ - C++ memory_order_acquire/release问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63519762/

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