简体   繁体   English

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

[英]std::thread thread spun off in object, when does it terminate?

If I spin off an std::thread in the constructor of Bar when does it stop running? 如果我在Bar的构造函数中关闭std::thread ,它什么时候停止运行? Is it guaranteed to stop when the Bar instance gets destructed? Bar实例被破坏时,它是否可以保证停止?

class Bar {

public:

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

...

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

}

private:
  std::thread thread;

};

EDIT: How do I correctly terminate the std::thread in the destructor? 编辑:如何正确终止析构函数中的std::thread

If I spin off an std::thread in the constructor of Bar when does it stop running? 如果我在Bar的构造函数中关闭std :: thread,它什么时候停止运行?

the thread will run as long as it executing the callable you provided it, or the program terminates. 只要它执行你提供的调用,或者程序终止,线程就会运行。

Is it guaranteed to stop when the Bar instance gets destructed? 当Bar实例被破坏时,它是否可以保证停止?

No. In order to guarantee that, call std::thread::join in Bar destructor. 不。为了保证这一点,在Bar析构函数中调用std::thread::join

Actually, if you hadn't call thread::join or thread::detach prior to Bar::~Bar , than your application will be terminated by calling automatically to std::terminate . 实际上,如果你没有在Bar::~Bar之前调用thread::jointhread::detach ,那么你的应用程序将通过自动调用std::terminatestd::terminate so you must call either join (preferable) or detach (less recommended). 所以你必须要么join (优先)或detach (少推荐)。

you also want to call therad::join on the object destructor because the spawned thread relies on the object to be alive , if the object is destructed while your thread is working on that object - you are using destructed object and you will have undefined behavior in your code. 你还想在对象析构函数上调用therad::join ,因为生成的线程依赖于对象是活的 ,如果在你的线程处理该对象时对象被破坏 - 你正在使用被破坏的对象而你将有未定义的行为在你的代码中。

Short answer: Yes and no. 简短的回答:是的,不是。 Yes, the thread ends, but not by the usual way (killing the thread), but by the main thread exiting due to a std::terminate call. 是的,线程结束,但不是通常的方式(杀死线程),而是由于std::terminate调用退出的主线程。

Long answer: The thread can only be safely destructed when the underlying function ( thread ) has finished executing. 答案很长:只有在底层函数( 线程 )执行完毕后才能安全地破坏线程 This can be done in 2 ways 这可以通过两种方式完成

  • calling join() , which waits for the thread to finish (in your case, never) 调用join() ,等待线程完成(在你的情况下,永远不会)
  • calling detach() , which detaches the thread from the main thread (in this case, the thread will end when the main thread closes - when the program terminates). 调用detach() ,它将线程与主线程分离(在这种情况下,线程将在主线程关闭时结束 - 当程序终止时)。

If the destructor is called if all of those conditions don't apply, then std::terminate is called: 如果在所有这些条件都不适用的情况下调用析构函数,则调用std::terminate

  • it was default-constructed 它是默认构造的

  • it was moved from 它被移走了

  • join() has been called 已调用join()

  • detach() has been called 已经调用了detach()

The C++ threading facilities do not include a built-in mechanism for terminating a thread. C ++线程工具包含用于终止线程的内置机制。 Instead, you must decide for yourself: a) a mechanism to signal the thread that it should terminate, b) that you do not care about the thread being aborted mid-operation when the process terminates and the OS simply ceases to run it's threads any more. 相反,你必须自己决定:a)一个机制来通知线程它应该终止,b)你不关心线程在进程终止时在操作中被中止并且操作系统只是停止运行它的线程任何更多。

The std::thread object is not the thread itself but an opaque object containing a descriptor/handle for the thread, so in theory it could be destroyed without affecting the thread, and there were arguments for and against automatic termination of the thread itself. std::thread对象不是线程本身,而是包含线程的描述符/句柄的不透明对象,因此理论上它可以在不影响线程的情况下被销毁,并且存在支持和反对线程自动终止的参数。 Instead, as a compromise, it was made so that destroying a std::thread object while the thread remained running and attached would cause the application to terminate. 相反,作为妥协,它是这样做的,以便在线程保持运行和附加时销毁std::thread对象将导致应用程序终止。

As a result, In it's destructor there is some code like this: 结果,在它的析构函数中有一些代码如下:

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

Here's an example of using a simple atomic variable and checking for it in the thread. 这是一个使用简单原子变量并在线程中检查它的示例。 For more complex cases you may need to consider a condition_variable or other more sophisticated signaling mechanism. 对于更复杂的情况,您可能需要考虑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";
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM