MS *_*nth 6 c++ multithreading c++11 relaxed-atomics
我试图了解 memory_order_relaxed 的细节。我指的是这个链接:CPP 参考。
#include <future>
#include <atomic>
std::atomic<int*> ptr {nullptr};
void fun1(){
ptr.store(new int{0}, std::memory_order_relaxed);
}
void fun2(){
while(!ptr.load(std::memory_order_relaxed));
}
int main(){
std::async(std::launch::async, fun1);
std::async(std::launch::async, fun2);
}
Run Code Online (Sandbox Code Playgroud)
问题1:在上面的代码中,即使设置ptr的线程已经完成运行,fun2在技术上是否可能处于无限循环中,它看到ptr的值为nullptr?
如果假设,我将上面的代码更改为如下所示:
#include <future>
#include <atomic>
std::atomic<int> i {0};
std::atomic<int*> ptr {nullptr};
void fun1(){
i.store(1, std::memory_order_relaxed);
i.store(2, std::memory_order_relaxed);
ptr.store(new int{0}, std::memory_order_release);
}
void fun2(){
while(!ptr.load(std::memory_order_acquire));
int x = i.load(std::memory_order_relaxed);
}
int main(){
std::async(std::launch::async, fun1);
std::async(std::launch::async, fun2);
}
Run Code Online (Sandbox Code Playgroud)
相关问题:在上面的代码中,fun2 是否有可能将原子 i 的值视为 1 或者是否可以保证它会看到值 2?
一个有趣的观察是,对于您的代码,没有实际的并发性;即fun1并按fun2顺序运行,原因是在特定条件下(包括std::async使用std::launch::async启动策略调用),std::future返回的对象std::async具有其析构函数块,直到启动的函数调用返回。由于您忽略了返回对象,因此在语句结束之前调用其析构函数。如果您颠倒了main()(即fun2在之前启动fun1)中的两个语句,您的程序将陷入无限循环,因为fun1永远不会运行。
这种std::future等待销毁行为有些争议(即使在标准委员会内部),并且由于我认为您不是这个意思,我将冒昧地将mainfor(两个示例)中的 2 个语句重写为:
auto tmp1 = std::async(std::launch::async, fun1);
auto tmp2 = std::async(std::launch::async, fun2);
Run Code Online (Sandbox Code Playgroud)
这将推迟实际std::future返回的对象破坏,直到结束main,这样fun1并fun2获得异步运行。
fun2 在技术上是否可能处于无限循环中,即使设置 ptr 的线程已完成运行,它也会将 ptr 的值视为 nullptr?
不,这是不可能的std::atomic(在真实平台上,如评论部分所述)。对于非std::atomic变量,编译器可以(理论上)选择仅将值保留在寄存器中,但std::atomic存储 a 并且缓存一致性会将值传播到其他线程。std::memory_order_relaxed只要您不取消引用指针,在这里使用就可以了。
在上面的代码中,fun2 是否有可能将原子 i 的值视为 1,或者是否可以保证它会看到值 2?
保证在变量中看到值 2 x。
fun1将两个不同的值存储到同一个变量中,但由于存在明确的依赖关系,因此不会对它们进行重新排序。
在 中fun1,ptr.storewithstd::memory_order_release防止i.store(2)withstd::memory_order_relaxed向下移动到其释放屏障以下。在 中fun2,ptr.loadwithstd::memory_order_acquire防止i.loadwithstd::memory_order_relaxed向上移动越过它的获取障碍。这保证了xin 的fun2值为 2。
注意,通过使用std::memory_order_relaxed上所有原子公司,这将是可以看到x具有值0,1或2,这取决于接入原子变量的相对顺序i与问候ptr.store和ptr.load。
| 归档时间: |
|
| 查看次数: |
4261 次 |
| 最近记录: |