gpt4 book ai didi

c++ - 是否可以将宽松的内存顺序效果扩展到执行线程的生命之后?

转载 作者:搜寻专家 更新时间:2023-10-31 00:59:56 26 4
gpt4 key购买 nike

假设在 C++11 程序中,我们有一个名为 A 的主线程,它启动一个名为 B 的异步线程。在线程 B 中,我们使用 std::memory_order_relaxed 内存顺序对原子变量执行原子存储。然后线程 A 与线程 B 连接。然后线程 A 启动另一个名为 C 的线程,该线程以 std::memory_order_relaxed 内存顺序执行原子加载操作。有没有可能线程C加载的内容和线程B写的内容不一样?换句话说,这里宽松的内存一致性是否会延伸到线程生命周期之后?

为了尝试这个,我编写了一个简单的程序并多次尝试运行它。该程序不会报告不匹配。我在想,因为线程 A 在线程启动时强加了一个顺序,所以不匹配是不可能发生的。但是,我不确定。

#include <atomic>
#include <iostream>
#include <future>

int main() {

static const int nTests = 100000;
std::atomic<int> myAtomic( 0 );

auto storeFunc = [&]( int inNum ){
myAtomic.store( inNum, std::memory_order_relaxed );
};

auto loadFunc = [&]() {
return myAtomic.load( std::memory_order_relaxed );
};

for( int ttt = 1; ttt <= nTests; ++ttt ) {
auto writingThread = std::async( std::launch::async, storeFunc, ttt );
writingThread.get();
auto readingThread = std::async( std::launch::async, loadFunc );
auto readVal = readingThread.get();
if( readVal != ttt ) {
std::cout << "mismatch!\t" << ttt << "\t!=\t" << readVal << "\n";
return 1;
}
}

std::cout << "done.\n";
return 0;

}

最佳答案

在可移植线程平台通常为您提供指定内存可见性或设置显式内存屏障的能力之前,可移植同步完全是通过显式同步(如互斥锁)和隐式同步来完成的。

一般在创建线程之前,都会设置一些线程启动时会访问的数据结构。为了避免仅仅为了实现这种通用模式而必须使用互斥锁,线程创建被定义为隐式同步事件。加入一个线程然后查看它计算的一些结果同样常见。同样,为了避免仅仅为了实现这种通用模式而必须使用互斥体,加入线程被定义为隐式同步事件。

由于线程创建和结构被定义为同步操作,加入线程必然发生在该线程终止之后。因此,您将看到任何线程终止之前必然发生的事情。更改一些变量然后创建线程的代码也是如此——新线程必然会看到创建它之前发生的所有更改。线程创建或终止时的同步就像互斥锁上的同步。同步操作创建了这种确保内存可见性的排序关系。

正如 SergeyA 所提到的,您绝对不应该尝试通过测试来证明多线程世界中的某些东西。当然,如果测试失败,那就证明你不能依赖你测试的东西。但是,即使测试通过您能想到的所有测试方式都成功了,这并不意味着它不会在您未测试的某些平台、CPU 或库上失败。你永远无法通过那种测试来证明这样的东西是可靠的。

关于c++ - 是否可以将宽松的内存顺序效果扩展到执行线程的生命之后?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32338000/

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