std::memory_order_relaxed和初始化

std::memory_order_relaxed and initialization

本文关键字:初始化 relaxed order std memory      更新时间:2023-10-16

以下内容是否保证先打印1后打印2?

auto&& atomic = std::atomic<int>{0};
std::atomic<int>* pointer = nullptr;
// thread 1
auto&& value = std::atomic<int>{1};
pointer = &value;
atomic.store(1, std::memory_order_relaxed);
while (atomic.load(std::memory_order_relaxed) != 2) {}
cout << value.load(std::memory_order_relaxed) << endl;
// thread 2
while (atomic.load(std::memory_order_relaxed) != 1) {}
cout << pointer->load(std::memory_order_relaxed); << endl;
pointer->fetch_add(1, std::memory_order_relaxed);
atomic.store(2, std::memory_order_relaxed) {}

如果没有,这里可能的输出是什么?对于这种情况,标准对初始化和内存顺序有何规定?

如注释中所述,使用"宽松"排序可以防止任何必要的线程间同步,因此,对pointer的访问是不同步的(或无序的(
这意味着线程2可以取消引用pointer,而它仍然具有值nullptr
此外,由于pointer是非原子类型(即常规指针(,因此可能无法在线程之间以这种方式访问它。从技术上讲,你有一场数据竞赛,这会导致未定义的行为。

一个解决方案是稍微加强内存排序。我认为在atomic上使用获取/发布命令就足够了:

auto&& atomic = std::atomic<int>{0};
std::atomic<int>* pointer = nullptr;
// thread 1
auto&& value = std::atomic<int>{1};
pointer = &value;
atomic.store(1, std::memory_order_release);
while (atomic.load(std::memory_order_acquire) != 2) {}
cout << value.load(std::memory_order_relaxed) << endl;
// thread 2
while (atomic.load(std::memory_order_acquire) != 1) {}
cout << pointer->load(std::memory_order_relaxed); << endl;
pointer->fetch_add(1, std::memory_order_relaxed);
atomic.store(2, std::memory_order_release) {}

有了这个订单,结果就可以保证打印

1
2