为什么即使调用了析构函数,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 线程(它只是在等待线程的完成)或 detaching 从它。

当调用std::thread析构函数时,线程句柄也被析构,无法进一步控制线程。但是执行线程本身仍然存在并继续由实现(或者更准确地说,操作系统)管理。

请注意,对于非分离线程 std::thread,如果线程尚未加入,则析构函数会抛出异常。这只是一种保护措施,可防止开发人员意外丢失线程句柄。