gpt4 book ai didi

c++ - 了解 memory_order_relaxed

转载 作者:太空狗 更新时间:2023-10-29 21:17:59 26 4
gpt4 key购买 nike

我试图了解 memory_order_relaxed 的细节。我指的是这个链接:CPP Reference .

#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);
}

问题 1:在上面的代码中,fun2 在技术上是否可能处于无限循环中,即使设置 ptr 的线程已完成运行,它也会将 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);
}

相关问题:在上面的代码中,fun2 是否有可能将 atomic i 的值视为 1,或者确定它会看到值 2?

最佳答案

一个有趣的观察是,对于您的代码,没有实际的并发;即 fun1fun2 按顺序运行,原因是在特定条件下(包括使用 std 调用 std::async: :launch::async 启动策略),由 std::async 返回的 std::future 对象具有其析构函数 block ,直到启动的函数调用返回。由于您忽略了返回对象,因此它的析构函数在语句结束之前被调用。如果您颠倒了 main() 中的两个语句(即在 fun1 之前启动 fun2),您的程序就会陷入无限循环,因为fun1 永远不会运行。

这种 std::future 等待销毁的行为有些争议(即使在标准委员会内部也是如此),因为我认为你不是那个意思,我会冒昧地重写main 中的 2 个语句(两个示例)用于:

auto tmp1 = std::async(std::launch::async, fun1);
auto tmp2 = std::async(std::launch::async, fun2);

这会将实际的 std::future 返回对象销毁推迟到 main 结束,以便 fun1fun2 开始异步运行。

is it technically possible for fun2 to be in an infinite loop where it sees the value of ptr as nullptr even if the thread that sets ptr has finished running?

不,这对于 std::atomic 是不可能的(在真实平台上,如评论部分所述)。对于非 std::atomic 变量,编译器可以(理论上)选择仅将值保留在寄存器中,但 std::atomic 会被存储和缓存一致性会将值传播到其他线程。只要您不取消引用指针,就可以在这里使用 std::memory_order_relaxed

Is it possible in the code above for fun2 to see the value of atomic i as 1 or is it assured that it will see the value 2?

保证在变量 x 中看到值 2。
fun1 将两个不同的值存储到同一个变量中,但由于存在明确的依赖关系,因此不会重新排序。

fun1 中,带有 std::memory_order_releaseptr.store 阻止了 i.store(2) 随着 std::memory_order_relaxed 向下移动到其释放屏障以下。在 fun2 中,ptr.load with std::memory_order_acquire 阻止 i.load with std::memory_order_relaxed 从获取障碍向上移动。这保证 fun2 中的 x 的值为 2。

请注意,通过对所有 原子使用std::memory_order_relaxed,可以看到x 的值为0、1 或2 ,取决于访问原子变量 iptr.storeptr.load 的相对顺序。

关于c++ - 了解 memory_order_relaxed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31150809/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com