C++ 告诉 std::thread 在满足条件时杀死/停止自己

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18868114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:16:07  来源:igfitidea点击:

Telling an std::thread to kill/stop itself when a condition is met

c++multithreadingc++11stdthread

提问by alxcyl

Say I have a worker thread tWorker, which is initialized when Bossis constructed and tells it to do work(), until bRetiredis true. An std::mutex, mtx, locks some data (vFiles) so that tWorkerowns it when he's working on it.

假设我有一个工作线程tWorker,它在Boss构造时初始化并告诉它执行work(),直到bRetired为真。一std::mutexmtx,锁定一些数据(vFiles),使tWorker拥有它的时候,他的工作就可以了。

How do I make tWorker"commit suicide" once bRetiredbecomes true? How would the mutexbe destroyed when the thread stops execution?

我如何让tWorker“自杀”一旦bRetired变成truemutex线程停止执行时如何销毁?

I've read that std::threadobjects cannot be interrupted in any way. Does letting the thread do nothing (or calling std::this_thread::yield()) provide the same effect as killing the thread?

我读过std::thread不能以任何方式中断对象。让线程什么都不做(或调用std::this_thread::yield())与杀死线程的效果相同吗?

class Boss {
private:
    std::thread tWorker;
    std::mutex mtx;
    bool bRetired;
    std::vector< std::string > vFiles;

    void work() {
        while ( bRetired == false ) {
            // Do your job!
            mtx.lock();
            // ... Do something about vFiles ...
            mtx.unlock();
        }

        // tWorker has retired, commit suicide
        // ** How? **

        // Does this suffice if I want to "kill" the thread?
        std::this_thread::yield(); 
    }

public:
    Boss() {
        bRetired = false;
        tWorker = std::thread( &Boss::work, this );

        // Have worker do its job independently
        // **Bonus Question** : Should this be tWorker.join() or tWorker.detach()?
        tWorker.detach();
    }

    retire() {
        bRetired = true;
    }
}

Notes

笔记

  • The worker thread cannot be started again once it is retired.
  • The worker thread works on the background without interrupting the main thread's execution.
  • 工作线程一旦退役就无法再次启动。
  • 工作线程在后台工作,不会中断主线程的执行。

采纳答案by hmjd

The call to std::thread::yield()is unrequired and does not kill the calling thread:

std::thread::yield()不需要调用并且不会终止调用线程:

Provides a hint to the implementation to reschedule the execution of threads, allowing other threads to run.

向实现提供提示以重新安排线程的执行,从而允许其他线程运行。

Just exit the function to exit the thread.

只需退出函数即可退出线程。

Note that the use of bRetiredis incorrect as two threads can be accessing the same memory location and one of those threads is modifying it: this is undefined behaviour. Also, the change made in the function retire(), a different thread, will not be seen by the thread executing run(): use atomic<bool>for atomicity and visibility.

请注意,使用bRetired是不正确的,因为两个线程可以访问相同的内存位置,而其中一个线程正在修改它:这是未定义的行为。此外,在函数中所做的更改retire(),一个不同的线程,不会被执行的线程看到run()atomic<bool>用于原子性和可见性。

If join()was used within the constructor the constructor would not return until the thread exited, which would never happen as it would be impossible to call retire()because the object would not be available (as the constructor would not have returned). If it is required to synchronize with the exiting of the thread then do not detach()but join()in the retire()function:

如果join()在构造函数中使用,则构造函数在线程退出之前不会返回,这永远不会发生,retire()因为无法调用,因为对象不可用(因为构造函数不会返回)。如果需要与线程的退出同步,则不要detach()join()retire()函数中:

void retire() {
    bRetired = true;
    tWorker.join();
}

Use RAII for acquiring mutexes (std::lock_guardfor example) to ensure it always released. The mutexwill be destroyed when it goes out of scope, in this case when its containing class is destructed.

使用 RAII 获取mutexes(std::lock_guard例如)以确保它始终被释放。在mutex当它超出范围,在这种情况下,当其包含的类被破坏就会被破坏。

回答by Maxim Egorushkin

How do I make tWorker "commit suicide" once bRetired becomes true?

一旦 bRetired 变为真,我如何让 tWorker “自杀”?

You let the control flow exit the thread function. That std::this_thread::yield()call in unnecessary.

你让控制流退出线程函数。那个std::this_thread::yield()电话是不必要的。

How would the mutex be destroyed when the thread stops execution?

当线程停止执行时,互斥量将如何销毁?

That mutex is a member of Bossclass. It gets destroyed in the destructor of Bosswhen the object is getting destroyed.

该互斥体是Boss类的成员。它Boss在对象被销毁时的析构函数中被销毁。

I've read that std::thread objects cannot be interrupted in any way.

我读过 std::thread 对象不能以任何方式中断。

C++ API does not provide means to terminate an arbitrary thread. There has to be a way to tell a thread to terminate and then wait till it does, as you intend to do.

C++ API 不提供终止任意线程的方法。必须有一种方法告诉线程终止,然后按照您的意图等待它终止。

Does letting the thread do nothing (or calling std::this_thread::yield()) provide the same effect as killing the thread?

让线程什么都不做(或调用 std::this_thread::yield() )是否提供与杀死线程相同的效果?

No.

不。

There is a race condition on bRetiredvariable though. It either needs to be std::atomic<bool>or it should only be read and modified only when that mutex is locked.

bRetired但是,变量存在竞争条件。它要么需要,要么std::atomic<bool>只有在该互斥锁被锁定时才能读取和修改。