std :: thread thread在对象中分离出来,什么时候终止?

时间:2016-10-19 17:44:00

标签: c++ multithreading c++11 stdthread

如果我在std::thread的构造函数中关闭Bar何时停止运行?是否保证在Bar实例被破坏时停止?

class Bar {

public:

Bar() : thread(&Bar:foo, this) {
}

...

void foo() {
  while (true) {//do stuff//}

}

private:
  std::thread thread;

};

编辑:如何在析构函数中正确终止std::thread

3 个答案:

答案 0 :(得分:2)

  

如果我在Bar的构造函数中关闭std :: thread的话   停止运行?

只要执行你提供的callable,程序就会终止运行。

  

当Bar实例被破坏时,它是否可以保证停止?

没有。为了保证这一点,请在std::thread::join析构函数中调用Bar

实际上,如果您在thread::join之前没有致电thread::detachBar::~Bar,则会自动致电std::terminate来终止您的申请。所以必须调用join(首选)或detach(不太推荐)。

你还想在对象析构函数上调用therad::join因为生成的线程依赖于对象是活着的,如果在你的线程处理该对象时对象被破坏 - 您正在使用被破坏的对象,并且您的代码中将存在未定义的行为。

答案 1 :(得分:0)

简短回答:是和否。是的,线程结束,但不是通常的方式(杀死线程),而是由于<div id="wrapper-for-demo"><!-- just to fit nicely in the stacksnippets results window --> <!-- an image with a square source --> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" style="background-image:url(http://placehold.it/400x400)" /> <!-- an image with a non-square source --> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" style="background-image:url(http://placehold.it/400x600)" /> </div>调用而退出的主线程。

答案很长:当底层函数( thread )完成执行时,只能安全地破坏线程。这可以通过两种方式完成

  • 调用std::terminate,等待线程完成(在您的情况下,永远不会)
  • 调用join(),它将线程与主线程分离(在这种情况下,线程将在主线程关闭时结束 - 当程序终止时)。

如果所有those conditions都不适用,则调用析构函数,然后调用detach()

  
      
  • 它是默认构造的

  •   
  • 它已从

  • 移出   
  • std::terminate被称为

  •   
  • join()被称为

  •   

答案 2 :(得分:0)

C ++线程工具包含用于终止线程的内置机制。相反,你必须自己决定:a)一个机制来通知线程它应该终止,b)你不关心线程在进程终止时中止操作并且操作系统只是停止运行它#39 ; s线程了。

std::thread对象不是线程本身,而是包含线程描述符/句柄的不透明对象,因此理论上它可以在不影响线程的情况下被销毁,并且有支持和反对自动终止的参数线程本身。相反,作为妥协,它是这样做的,以便在线程保持运行和附加时销毁std::thread对象将导致应用程序终止。

结果,在它的析构函数中有一些代码如下:

~thread() {
    if (this->joinable())
        std::terminate(...);
}

这是一个使用简单原子变量并在线程中检查它的示例。对于更复杂的情况,您可能需要考虑condition_variable或其他更复杂的信令机制。

#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>

class S {
    std::atomic<bool> running_;
    std::thread thread_;
public:
    S() : running_(true), thread_([this] () { work(); }) {}
    void cancel() { running_ = false; }
    ~S() {
        if ( running_ )
            cancel();
        if ( thread_.joinable() )
            thread_.join();
    }
private:
    void work() {
        while ( running_ ) {
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
            std::cout << "tick ...\n";
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
            std::cout << "... tock\n";
        }
        std::cout << "!running\n";
    }
};

int main()
{
    std::cout << "main()\n";
    {
        S s;
        std::this_thread::sleep_for(std::chrono::milliseconds(2750));
        std::cout << "end of main, should see a tock and then end\n";
    }
    std::cout << "finished\n";
}

现场演示:http://coliru.stacked-crooked.com/a/3b179f0f9f8bc2e1