men*_*oom 6 c++ multithreading
我需要一些关于 thread_local 对象销毁的澄清。第一个问题是什么时候发生?C++ 参考资料如下:
对象的存储在线程开始时分配,并在线程结束时释放。每个线程都有自己的对象实例。只有声明为 thread_local 的对象才具有此存储持续时间。
不幸的是,线程何时结束并不总是显而易见的。让我们考虑以下示例:
#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>
#include <mutex>
struct MyClass
{
MyClass()
{
std::scoped_lock<std::mutex> lck(mtx);
std::cout << "ctor" << std::endl << std::flush;
}
~MyClass()
{
std::scoped_lock<std::mutex> lck(mtx);
std::cout << "dtor" << std::endl << std::flush;
}
static std::mutex mtx;
};
std::mutex MyClass::mtx;
int main(int argc, char* argv[])
{
std::vector<int> v(1000000, 3);
std::transform(std::execution::par, v.begin(), v.end(), v.begin(), [](int x)
{
thread_local MyClass myclass;
return x * x;
});
std::cout << "done" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
直觉上我希望线程在std::transform()调用返回时结束。然而,看起来 MyClass 的 thread_local 对象会继续存在,直到程序结束。此外,其中一些根本没有被破坏。这引出了另一个问题。
当我在 MSVC 2019 (16.8.6) 中测试此示例代码时,调用了多个构造函数,但始终只有一个析构函数:
ctor
ctor
ctor
ctor
ctor
done
dtor
Run Code Online (Sandbox Code Playgroud)
我在 MSVC 中读过关于此行为的另一篇文章。如果我理解正确的话,这个问题是由Windows系统线程池引起的,并且一定是Windows特定的。所以我决定在 Linux 上使用 GCC 9.3.0 进行测试:
ctor
ctor
ctor
ctor
ctor
ctor
done
dtor
dtor
dtor
dtor
Run Code Online (Sandbox Code Playgroud)
现在调用了多个析构函数,但在上面的示例中我们仍然可以看到构造函数和析构函数调用的数量不匹配。这是一个错误还是一个设计的行为?怎么能说得过去呢?