我什么时候应该使用std :: thread :: detach?

时间:2014-04-02 06:51:44

标签: c++ c++11 stdthread

有时我必须使用std::thread来加速我的申请。我也知道join()等待一个线程完成。这很容易理解,但是调用detach()而不调用它有什么区别?

我认为没有detach(),线程的方法将独立使用线程。

不分离:

void Someclass::Somefunction() {
    //...

    std::thread t([ ] {
        printf("thread called without detach");
    });

    //some code here
}

分离呼叫:

void Someclass::Somefunction() {
    //...

    std::thread t([ ] {
        printf("thread called with detach");
    });

    t.detach();

    //some code here
}

5 个答案:

答案 0 :(得分:115)

std::thread的析构函数中,{:1}}在以下情况下被调用:

  • 线程未加入(使用std::terminate
  • 并且没有分离(使用t.join()

因此,在执行流程到达析构函数之前,您应该总是t.detach()join一个线程。


当程序终止时(即detach返回),不等待在后台执行的剩余分离线程;相反,他们的执行被暂停,他们的线程本地对象被破坏。

至关重要的是,这意味着这些线程的堆栈没有解开,因此一些析构函数不会被执行。根据这些破坏者应该采取的行动,这可能就像程序崩溃或被杀死一样糟糕。希望操作系统将释放文件锁等...但你可能已经损坏了共享内存,半写文件等。


那么,您应该使用main还是join

  • 使用detach
  • 除非你需要更多的灵活性并且愿意提供同步机制来等待你自己的线程完成,在这种情况下你可以使用join

答案 1 :(得分:19)

如果您不打算等待线程完成detach,则应该调用join,但线程将继续运行直到完成,然后在没有主线程等待的情况下终止特别是。

detach基本上会释放能够实施join所需的资源。

如果一个线程对象结束其生命并且joindetach都没有被调用,那么这是一个致命错误;在这种情况下,terminate被调用。

答案 2 :(得分:8)

当您分离线程时,这意味着您在退出join()之前不需要main()

线程库实际上会等待每个这样的线程 under-main ,但你不应该关心它。

detach()主要用于必须在后台完成的任务,但不关心它的执行。这通常是某些图书馆的情况。他们可以默默地创建一个后台工作线程并将其分离,这样你甚至都不会注意到它。

答案 3 :(得分:3)

此答案旨在回答标题中的问题,而不是解释joindetach之间的区别。那么什么时候应该使用std::thread::detach

在正确维护的C ++代码std::thread::detach中,根本不应该使用。程序员必须确保所有创建的线程正常退出以释放所有获取的资源并执行其他必要的清理操作。这意味着通过调用detach放弃线程所有权不是一种选择,因此在所有情况下都应使用join

但是,某些应用程序依赖于可能包含无限阻塞功能的旧的且通常设计不完善且受支持的API。将这些函数的调用移到专用线程中以避免阻塞其他内容是一种常见的做法。无法使此类线程正常退出,因此使用join只会导致主线程阻塞。在这种情况下,使用detach而不是用动态存储持续时间分配thread对象然后有意地泄漏它,是一种不太邪恶的选择。

#include <LegacyApi.hpp>
#include <thread>

auto LegacyApiThreadEntry(void)
{
    auto result{NastyBlockingFunction()};
    // do something...
}

int main()
{
    ::std::thread legacy_api_thread{&LegacyApiThreadEntry};
    // do something...
    legacy_api_thread.detach();
    return 0;
}

答案 4 :(得分:1)

根据cppreference.com

  

将执行线程与线程对象分离,从而允许   执行独立继续。任何分配的资源将是   线程退出后释放。

     

在调用分离*this之后,它不再拥有任何线程。

例如:

  std::thread my_thread([&](){XXXX});
  my_thread.detach();

请注意,局部变量my_threadmy_thread的生命周期结束时,将调用std::thread的析构函数,并且将在析构函数内调用std::terminate()

但是,如果您使用detach(),则不应再使用my_thread,即使my_thread的生命周期结束了,新线程也不会发生任何事情。