c++ - std::memory_order_relaxed 和初始化

标签 c++ multithreading concurrency atomic memory-barriers

以下内容是否保证打印 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/

相关文章:

c++ - 我可以在输入 BSTR VARIANT 上调用 VariantChangeType 吗?

linux - 没有 exec 的 fork,共享对象使用的 pthread_mutex_t

java - 当独立程序想要退出时,@Scheduled Tasks 使 JVM 保持挂起状态,需要杀死 JVM

java - 并发读取文件(首选java)

java - 嵌套 Scala Future 是否需要托管阻塞?

c++ - 段错误 :Why the array index here goes out of bounds?

c++ - 用于多个组件的索引技巧

c++ - 如何将 c/c++ 编写的函数访问到 ruby​​ 脚本中?

multithreading - Netty 需要在与 select() 相同的线程中发送,这会延迟发送

Java 并发 - 使用哪种技术来实现安全性?