std::memory_order_relaxed and initialization

谁都会走 提交于 2019-12-08 10:50:48

问题


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?


回答1:


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.

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


来源:https://stackoverflow.com/questions/51462208/stdmemory-order-relaxed-and-initialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!