等待 std::thread 完成

Posted

技术标签:

【中文标题】等待 std::thread 完成【英文标题】:Waiting for a std::thread to finish 【发布时间】:2013-11-13 18:53:25 【问题描述】:

我正在尝试在程序终止时优雅地清理,所以我在 std::thread 上调用 join() 以等待它完成。这似乎永远阻塞了主线程,但我不明白为什么,因为工作线程是一个(几乎)空循环,如下所示:

void GameLoop::Run()

    while (run)
    
        //  Do stuff... 
       
    std::cout << "Ending thread...\n";

当然,我在 joining 之前将 run 设置为 false。现在,我怀疑这与它是一个成员函数并在对象destruction 上被调用有关。我正在创建这样的线程:runThread.reset(new thread(&amp;GameLoop::Run, this));,其中runThreadunique_ptr&lt;std::thread&gt;GameLoop 的成员。 join() 调用来自 GameLoop 对象的析构函数。

如果它的对象正在被销毁,循环线程可能无法完成?根据调试器的说法,循环线程在msvcr120d.dll 的黑暗深处徘徊。如果有,你会怎么处理?

注意:这里是std::thread 的新手!

更新:这是我加入析构函数的呼吁:

run = false;
if (runThread->joinable())

    runThread->join();

更新 2:如果我删除 join(),我会收到 ~thread() 引发的异常!

【问题讨论】:

我希望你在某处将 run 设置为 false/0... 将其定义为 volatile 是个好主意。 你能贴出你的析构函数的相关代码吗? @AlexFarber - 将其定义为 std::atomic 是一个更好的主意。 volatile 没有可移植语义,对线程间同步没有用处。 如果你删除了 join(),你会得到一个异常,因为线程对象在线程完成之前不能被破坏(除非已经调用了 detach)。 我对你描述的代码的作用没有任何问题...coliru.stacked-crooked.com/a/7555dac44353ca50 【参考方案1】:

当然,当你join 一个线程不会导致线程终止。它只是阻塞,直到该线程因自然(或非自然)原因而死亡。

为了优雅地清理多线程应用程序,您需要以某种方式告诉工作线程它是时候死亡了,然后等待死亡发生。 “等待死亡发生”部分是 join 的用途。

【讨论】:

我将 run 设置为 false。让我更新一下问题。【参考方案2】:

啊,显然运行时库中存在错误。根据this question,在静态对象的析构函数中线程未成功结束。我的GameLoop 是一个包含在静态GameSystem 中的非静态对象。我会检查这是否属实并更新。

是的,已确认。在第一次使用时遇到错误只是我的运气!

【讨论】:

那么您还需要确保run 在多线程环境中正常运行。 好的,谢谢,我已将其更改为原子,但我想知道:对于像布尔这样的小变量,是否真的需要将其设为原子,如果有的话线程只写,另一个只读? @KristianD'Amato 不,如果当多个线程访问非原子变量的行为在 C++11 中是明确未定义的行为时,您愿意信任编译器。

以上是关于等待 std::thread 完成的主要内容,如果未能解决你的问题,请参考以下文章

C++ 杀死等待 std::thread

多个 std::threads 和主程序执行出现问题

如何销毁由 std::thread 显式创建的线程?

等待加入条件变量的线程会发生什么?

c++多线程在异常环境下的等待

C++ 11 std::thread 循环