在 C++ 中使用 std::atomic 与 std::condition_variable 暂停和恢复 std::thread 的方法

2024-05-07

这是一个单独的问题,但与我问的上一个问题相关here https://stackoverflow.com/questions/40544480/c-correct-way-to-pause-resume-an-stdthread/40544769?noredirect=1#comment68344743_40544769

我正在使用一个std::thread in my C++代码不断轮询一些数据并将其添加到缓冲区。我用一个C++ lambda像这样启动线程:

StartMyThread() {

    thread_running = true;
    the_thread = std::thread { [this] {
        while(thread_running) {
          GetData();
        }
    }};
}

thread_running is an atomic<bool>在类头中声明。这是我的GetData功能:

GetData() {
    //Some heavy logic
}

接下来我还有一个StopMyThread我设置的函数thread_running为 false 以便退出 while 循环lambda block.

StopMyThread() {
  thread_running = false;
  the_thread.join();
}

据我了解,我可以使用暂停和恢复线程std::condition_variable正如所指出的here https://stackoverflow.com/questions/40544480/c-correct-way-to-pause-resume-an-stdthread/40544769?noredirect=1#comment68344743_40544769在我之前的问题中。

但是如果我只使用有什么缺点吗std::atomic<bool> thread_running执行或不执行其中的逻辑GetData()像下面这样?

GetData() {
    if (thread_running == false)
      return;
    //Some heavy logic
}

与使用方法相比,这会消耗更多的 CPU 周期吗?std::condition_variable如上所述 here https://stackoverflow.com/questions/40544480/c-correct-way-to-pause-resume-an-stdthread/40544769?noredirect=1#comment68344743_40544769 ?


当您想要有条件地停止另一个线程时,条件变量非常有用。因此,您可能有一个始终运行的“工作”线程,当它发现与运行无关时,它会等待。

原子解决方案要求您的 UI 交互与工作线程同步,或者需要非常复杂的逻辑来异步执行。

作为一般规则,您的 UI 响应线程不应在工作线程的非就绪状态时阻塞。

struct worker_thread {
  worker_thread( std::function<void()> t, bool play = true ):
    task(std::move(t)),
    execute(play)
  {
    thread = std::async( std::launch::async, [this]{
      work();
    });
  }
  // move is not safe.  If you need this movable,
  // use unique_ptr<worker_thread>.
  worker_thread(worker_thread&& )=delete;
  ~worker_thread() {
    if (!exit) finalize();
    wait();
  }
  void finalize() {
    auto l = lock();
    exit = true;
    cv.notify_one();
  }
  void pause() {
    auto l = lock();
    execute = false;
  }
  void play() {
    auto l = lock();
    execute = true;
    cv.notify_one();
  }
  void wait() {
    Assert(exit);
    if (thread)
      thread.get();
  }
private:
  void work() {
    while(true) {
      bool done = false;
      {
        auto l = lock();
        cv.wait( l, [&]{
          return exit || execute;
        });
        done = exit; // have lock here
      }
      if (done) break;
      task();
    }
  }
  std::unique_lock<std::mutex> lock() {
     return std::unique_lock<std::mutex>(m);
  }
  std::mutex m;
  std::condition_variable cv;
  bool exit = false;
  bool execute = true;
  std::function<void()> task;
  std::future<void> thread;
};

或类似的东西。

它拥有一个线程。线程重复运行任务,只要它在play()模式。如果你pause()下一次task()完成后,工作线程停止。如果你play()之前task()通话结束,它没有注意到pause().

唯一的等待就是毁灭worker_thread,它会自动通知工作线程它应该退出并等待它完成。

您可以手动.wait() or .finalize()以及。.finalize()是异步的,但如果您的应用程序正在关闭,您可以尽早调用它,并给工作线程更多的时间来清理,同时主线程会清理其他地方的东西。

.finalize()无法逆转。

代码未测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C++ 中使用 std::atomic 与 std::condition_variable 暂停和恢复 std::thread 的方法 的相关文章

随机推荐