10

假设我有一个工作线程,它在构造tWorker时初始化并告诉它执行,直到为真。An , , 锁定一些数据 ( ) 以便在他处理它时拥有它。Bosswork()bRetiredstd::mutexmtxvFilestWorker

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

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

笔记

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

2 回答 2

6

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

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

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

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

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

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

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

不。

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

于 2013-09-18T09:22:11.093 回答
5

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

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

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

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

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

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

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

于 2013-09-18T09:20:54.407 回答