std :: memory_order_relaxed和初始化 [英] std::memory_order_relaxed and initialization

查看:619
本文介绍了std :: memory_order_relaxed和初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is the following guaranteed to print 1 followed by 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) {}

如果没有,这里可能的输出是什么?在这种情况下,标准对初始化和存储顺序有何看法?

If not, what are the possible outputs here? What does the standard say about initialization and memory orders for this case?

推荐答案

如注释中所述,使用松弛"排序可防止发生任何必要的线程间同步,因此对pointer的访问不同步(或无序).
这意味着线程2仍可以取消引用pointer,同时它仍具有值nullptr.
另外,由于pointer是非原子类型(即常规指针),因此可能无法在线程之间以这种方式访问​​它. 从技术上讲,您存在数据争用问题,这将导致未定义的行为.

As mentioned in a comment, the use of 'relaxed' ordering prevents any necessary inter-thread synchronization from happening and so, access to pointer is unsynchroinzed (or unordered).
That means thread 2 may dereference pointer while it still has the value nullptr.
Also, since pointer is a non-atomic type (i.e. a regular pointer), it may not be accessed this way between threads. Technically you have a data race, and that leads to undefined behavior.

一种解决方案是稍微增强内存排序.我认为在atomic上使用获取/发布顺序应该足够了:

A solution is to strengthen memory ordering a bit. I think using acquire/release ordering on atomic should be sufficient:

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) {}

有了此顺序,就可以保证打印出结果

With this ordering in place, the outcome is guaranteed to print

1
2

这篇关于std :: memory_order_relaxed和初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆