在IT技术中,分离一个线程然后让它超出作用域(并且仍然运行)是否安全?

13
我有以下代码,我认为它可以正常工作(请原谅这个愚蠢/牵强的例子)。
void run_thread()
{
    std::thread t([]{
        while(true)
        {
            // keep getting chars... to stop peoples eye's hurting : )
            char c = getchar();
        }
    });

    t.detach(); // Detach thread

    // thread goes out of scope here - but is it ok because its detached??
}

int main()
{
     run_thread();    

    // Wait here forever
    while (true) {;}
}

但是在重新阅读之后,我对此表示怀疑。线程t超出了范围。我不能确定在调用detach()之后是否安全这样做... 我认为是安全的,但是我有一个疑问。 有人可以确认这是否是好/坏习惯吗?


阅读:http://en.cppreference.com/w/cpp/thread/thread/~thread - Richard Critten
1
这个std::thread析构函数的参考文献可能会很有用。 - Some programmer dude
@RichardCritten 是的,我确实看到了那个,但它说可以安全地销毁(并没有告诉我它仍然会正常运行)。即使是detach也说:“将执行线程与线程对象分离,允许独立执行。一旦线程退出,任何分配的资源都将被释放。调用detach之后,*this不再拥有任何线程。”但我只是想再次确认一下:) - code_fodder
离题了,但是一个永远运行的线程可能会给你带来一些惊喜。https://timsong-cpp.github.io/cppwp/n4659/intro.multithread#intro.progress-1 - StoryTeller - Unslander Monica
@rustyx...哈哈,抱歉,好的我会的...我知道我应该举个更好的例子:o - code_fodder
4个回答

12

线程t超出作用域。我现在记不清是否安全在调用detach()之后这样做。

你使用detach()是因为你想将实际运行的线程与线程对象分离。所以在}之后,t超出作用域,但实际的线程将继续运行直到其指令完成。

如果没有detach(),则std::terminate会在}处终止线程。


这是关于std::terminate的一个非常好的观点..我没有想到过:) - code_fodder

3

detach 基本上释放了作为实际操作系统线程的C++“句柄”的std::thread对象实例,因此后续就无法使用 join 方法来加入线程。

在大多数情况下,最好将 thread 实例保留在某个全局范围内,以便稍后可以 join 它,例如在退出 main 之前。这样可以确保所有线程在主线程之前结束。

例如:

std::thread t; // can be "empty"

void run_thread()
{
    t = std::thread([]{
        while(true)
        {
            // keep getting chars...
            char c = getchar();
        }
    });

}

int main()
{
     run_thread();    

    // Wait here
    std::this_thread::sleep_for(30s);

    // Before exiting wait for the thread to finish
    if (t.joinable())
        t.join();
}

谢谢。我通常只使用这种方法,这就是为什么我对分离方法感到有些不舒服。但我认为这个答案对这个问题有所补充,所以给你点赞:) - code_fodder

1

是的,在你的代码中使用它是可以的和安全的。但这没有任何意义。 main 函数将利用 CPU,而线程函数将获得较少的 CPU 时间。您可以附加到永久线程并达到类似的行为:run_thread 永远不会退出,因此 main 也永远不会退出。

void run_thread()
{
    std::thread t([]{
        while(true){/* also run forever */;}
    });

    // Wait here forever
    t.attach();
}

int main()
{
     run_thread();    
}

是的,很抱歉这是由于我糟糕的示例 - 我只是拿出这个示例来展示“问题”。但你的意见已经被记录了: ) - code_fodder

1
这样的使用是detach的重点

啊,谢谢...正如我所想的那样,但我只是想向专业人士确认一下:)) - code_fodder
在程序(主线程)终止之前,仍需要确保该线程终止。 - Cheers and hth. - Alf
@Cheersandhth.-Alf 是的,说得好,我的真实代码中有一些线程同步,所以我应该没问题 :) - code_fodder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接