当条件满足时,告诉std :: thread杀死/停止它自己

时间:2013-09-18 09:10:31

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

假设我有一个工作线程tWorker,它在构造Boss时初始化,并告诉它work(),直到bRetired为真。 std::mutexmtx会锁定一些数据(vFiles),以便tWorker在处理数据时拥有该数据。

tWorker成为bRetired后如何让true“自杀”?当线程停止执行时,mutex将如何被销毁?

我已经读过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;
    }
}

备注

  • 工作线程退役后无法再次启动。
  • 工作线程在后台工作,不会中断主线程的执行。

2 个答案:

答案 0 :(得分:6)

  

一旦bRetired成为现实,我如何让tWorker“自杀”?

让控制流退出线程功能。 std::this_thread::yield()调用不必要的内容。

  

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

该互斥锁是Boss类的成员。当对象被破坏时,它会在Boss的析构函数中被破坏。

  

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

C ++ API不提供终止任意线程的方法。必须有一种方法告诉线程终止,然后等到它确实如你所愿。

  

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

没有

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

答案 1 :(得分:5)

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

  

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

退出该功能退出该线程。

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

如果在构造函数中使用join(),构造函数将不会返回,直到线程退出,这将永远不会发生,因为无法调用retire(),因为该对象将不可用(因为构造函数不会返回)。如果需要与线程的退出同步,那么detach()函数中不join()而是retire()

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

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