【问题标题】:Terminating an std::thread which runs in endless loop终止在无限循环中运行的 std::thread
【发布时间】:2016-10-22 19:49:00
【问题描述】:

如何在 Bar 的析构函数中终止我的分离线程(无需等到线程从睡眠中醒来)?

class Bar {

public:

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

~Bar() { // terminate thread here}



...

void foo() {
  while (true) {
     std::this_thread::sleep_for(
     std::chrono::seconds(LONG_PERIOD));

    //do stuff//
   }

}

private:
  std::thread thread;

};

【问题讨论】:

  • 你能在定时条件等待而不是硬睡眠的情况下入睡吗?
  • 您可以将while (true) { 更改为while (isDone) {,其中isDoneatomic<bool> 变量的成员。
  • @ NathanOliver 但是如果我分离它并且线程访问 Bar 的成员字段,则在 Bar 实例被破坏后行为将是未定义的
  • @user695652:您必须等待,直到LONG_PERIOD 超时。但是,使用条件变量,您可以阻止线程此后执行任何工作。虽然这解决了您之前的问题的一半,但您现在已经创建了一个新问题:您怎么知道您的线程在与数据分离时不在处理数据的中间?也许您可以提出一个基于弱指针的解决方案(在Bar 销毁时失效)。

标签: c++ multithreading c++11


【解决方案1】:

你可以使用std::condition_variable:

class Bar {
public:   
    Bar() : t_(&Bar::foo, this) { }
    ~Bar() { 
        {
            // Lock mutex to avoid race condition (see Mark B comment).
            std::unique_lock<std::mutex> lk(m_);
            // Update keep_ and notify the thread.
            keep_ = false;
        } // Unlock the mutex (see std::unique_lock)
        cv_.notify_one();
        t_.join(); // Wait for the thread to finish
    }

    void foo() {
        std::unique_lock<std::mutex> lk(m_);
        while (keep_) {
            if (cv_.wait_for(lk, LONG_PERIOD) == std::cv_status::no_timeout) {
                continue; // On notify, just continue (keep_ is updated).
            }   
            // Do whatever the thread needs to do...
        }
    }

private:
    bool keep_{true};
    std::thread t_;
    std::mutex m_;
    std::condition_variable cv_;
};

这应该让您对自己可以做什么有一个全局性的了解:

  • 您使用bool 来控制循环(使用std::mutex 进行受保护的读写访问);
  • 您使用std::condition_variable 来唤醒线程以避免等待LONG_PERIOD

【讨论】:

  • 如果您:(2) 检查保持,(1) 设置保持为假,(1) notify_one,(2) 获取锁,(2) 等待 (LONG_PERIOD),这不存在竞争条件通知?
  • @MarkB 可能...这是提供一个广泛的想法,我会尽可能更新代码。
  • dtor 需要释放 mutex,否则 CV 在其他线程中的等待永远不会唤醒。由于对 keep_ 的所有访问都是在互斥锁被锁定时完成的,因此它不需要是原子的。
  • @user695652 不要使用没有keep_ 的版本,请参阅 T.C. 的 cmets。
  • 好的,现在只是小问题:1) dtor 可以在不持有锁的情况下通知。 2) 在foo 的每次迭代中锁定和解锁互斥锁似乎没有意义。 3)使用wait_for的谓词版本可能更好。
猜你喜欢
  • 2021-06-30
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-31
相关资源
最近更新 更多