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

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

本文关键字:thread std 满足 条件 告诉      更新时间:2023-10-16

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

一旦bRetired变得true,如何让tWorker"自杀"?当线程停止执行时,如何销毁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;
    }
}

笔记

  • 工作线程一旦停用,就无法再次启动。
  • 工作线程
  • 在后台工作,而不会中断主线程的执行。

一旦b退休成为真的,我如何让tWorkers"自杀"?

让控制流退出线程函数。这std::this_thread::yield()不必要的

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

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

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

C++ API 不提供终止任意线程的方法。必须有一种方法可以告诉线程终止,然后等到它终止,就像你打算做的那样。

让线程不做任何事情(或调用 std::this_thread::yield())是否提供与杀死线程相同的效果?

不。

不过,bRetired变量上存在竞争条件。它要么需要std::atomic<bool>,要么只应在锁定该互斥锁时才读取和修改。

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 在超出范围时将被销毁,在这种情况下,当其包含类被销毁时。