以下内容是否保证打印 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) {}
如果不是,这里可能的输出是什么?对于这种情况,标准对初始化和内存顺序有何规定?
最佳答案
正如评论中提到的,使用“宽松”顺序可以防止发生任何必要的线程间同步,因此对指针
的访问是不同步的(或无序的)。
这意味着线程 2 可以取消引用 pointer
,同时它仍然具有值 nullptr
。
此外,由于指针是非原子类型(即常规指针),因此可能无法在线程之间以这种方式访问它。
从技术上讲,您存在数据竞争,这会导致未定义的行为。
解决方案是稍微加强内存排序。我认为在 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
关于c++ - std::memory_order_relaxed 和初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51462208/