为什么即使调用了析构函数,C++11 中的分离线程也能执行
Why can detached thread in C++11 execute even if the destructor has been called
我刚刚阅读了有关 std::thread.detach()
in C++11 的文档。
这是我的测试:
#include <iostream>
#include <thread>
#include <chrono>
static int counter = 0;
void func()
{
while (true) {
std::cout<<"running..."<<std::endl;
std::cout<<counter++<<std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
int main()
{
{
std::thread t(func);
t.detach();
} // t is released after this line
// t has died, so who is holding the resources of the detached thread???
std::cin.get();
return 0;
}
此代码按预期工作。所以看起来线程可以保持 运行 即使它的析构函数已经被调用。这是真的吗?
如果是真的,那么对象t被释放后,线程的资源到底是谁掌握的?是否有某种机制来保存资源,例如隐藏的匿名对象?
执行线程独立于您在 C++ 中用于管理它们的线程对象而存在。当你分离一个线程对象时,执行线程继续运行,但实现(通常与操作系统结合)负责它。
如果在线程的析构函数之后分离,线程保持 运行 是正确的。
地球上没有人拥有资源(除非您安排某人拥有)。但是,当您的应用程序退出时,应用程序关闭进程将结束线程。
仍然可以安排与 "wait" 分离线程进行通信。从本质上讲,join()
是一种便利 API,因此您不必执行以下操作:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
static int counter = 0;
std::atomic<bool> time_to_quit{false};
std::atomic<bool> has_quit{false};
void func()
{
while (!time_to_quit) {
std::cout<<"running..."<<std::endl;
std::cout<<counter++<<std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
has_quit = true;
}
int main()
{
{
std::thread t(func);
t.detach();
} // t is released after this line
using namespace std::chrono_literals;
std::this_thread::sleep_for(3s);
time_to_quit = true;
while (!has_quit)
;
std::cout << "orderly shutdown\n";
}
在 C++ 中,std::thread
不管理执行线程本身。 C++ 根本没有管理执行线程的控件。
std::thread
管理 线程句柄 - 线程的标识符(Posix 世界中的 thread_t
,这主要是一个模型std::thread
)。这种标识符用于与线程通信(如 control),但在 C++ 中,唯一的标准通信方式是 join
线程(它只是在等待线程的完成)或 detach
ing 从它。
当调用std::thread
析构函数时,线程句柄也被析构,无法进一步控制线程。但是执行线程本身仍然存在并继续由实现(或者更准确地说,操作系统)管理。
请注意,对于非分离线程 std::thread
,如果线程尚未加入,则析构函数会抛出异常。这只是一种保护措施,可防止开发人员意外丢失线程句柄。
我刚刚阅读了有关 std::thread.detach()
in C++11 的文档。
这是我的测试:
#include <iostream>
#include <thread>
#include <chrono>
static int counter = 0;
void func()
{
while (true) {
std::cout<<"running..."<<std::endl;
std::cout<<counter++<<std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
int main()
{
{
std::thread t(func);
t.detach();
} // t is released after this line
// t has died, so who is holding the resources of the detached thread???
std::cin.get();
return 0;
}
此代码按预期工作。所以看起来线程可以保持 运行 即使它的析构函数已经被调用。这是真的吗?
如果是真的,那么对象t被释放后,线程的资源到底是谁掌握的?是否有某种机制来保存资源,例如隐藏的匿名对象?
执行线程独立于您在 C++ 中用于管理它们的线程对象而存在。当你分离一个线程对象时,执行线程继续运行,但实现(通常与操作系统结合)负责它。
如果在线程的析构函数之后分离,线程保持 运行 是正确的。
地球上没有人拥有资源(除非您安排某人拥有)。但是,当您的应用程序退出时,应用程序关闭进程将结束线程。
仍然可以安排与 "wait" 分离线程进行通信。从本质上讲,join()
是一种便利 API,因此您不必执行以下操作:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
static int counter = 0;
std::atomic<bool> time_to_quit{false};
std::atomic<bool> has_quit{false};
void func()
{
while (!time_to_quit) {
std::cout<<"running..."<<std::endl;
std::cout<<counter++<<std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
has_quit = true;
}
int main()
{
{
std::thread t(func);
t.detach();
} // t is released after this line
using namespace std::chrono_literals;
std::this_thread::sleep_for(3s);
time_to_quit = true;
while (!has_quit)
;
std::cout << "orderly shutdown\n";
}
在 C++ 中,std::thread
不管理执行线程本身。 C++ 根本没有管理执行线程的控件。
std::thread
管理 线程句柄 - 线程的标识符(Posix 世界中的 thread_t
,这主要是一个模型std::thread
)。这种标识符用于与线程通信(如 control),但在 C++ 中,唯一的标准通信方式是 join
线程(它只是在等待线程的完成)或 detach
ing 从它。
当调用std::thread
析构函数时,线程句柄也被析构,无法进一步控制线程。但是执行线程本身仍然存在并继续由实现(或者更准确地说,操作系统)管理。
请注意,对于非分离线程 std::thread
,如果线程尚未加入,则析构函数会抛出异常。这只是一种保护措施,可防止开发人员意外丢失线程句柄。