正确的暂停方式&恢复std :: thread

时间:2016-11-11 09:05:55

标签: c++ c++11 lambda c++14 stdthread

我在std::thread代码中使用C++来不断轮询某些数据&将它添加到缓冲区。我使用C++ lambda来启动这样的线程:

StartMyThread() {

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

thread_running是在类标头中声明的atomic<bool>。这是我的GetData函数:

GetData() {
    //Some heavy logic which needs to be executed in a worker thread
}

接下来我还有一个StopMyThread函数,我将thread_running设置为false,以便它从lambda block中的while循环中退出。

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

效果很好。线程开始&amp;停止而不会崩溃。

此C ++代码用于iOS,Android,OS X和Windows。我的应用程序UI有一个按钮,需要我启动&amp;按下按钮停止线程;这个按钮可以在某些场合经常使用。我可以在停止或启动线程时看到UI中的瞬间延迟。

我的问题是: 在C ++中,这是一种经常启动/停止线程的正确方法吗?我认为通过这种逻辑我每个都创建一个新线程-时间。据我所知,创建一个新线程会使操作系统分配大量新资源,这些资源可能会耗费时间。我认为这是我正在做的错误。我怎么能避免这个?

如何在整个应用程序生命周期中不重复分配新线程的情况下使用同一个线程,并在需要时播放/暂停它?

1 个答案:

答案 0 :(得分:5)

这是使用条件变量的经典示例。您等待互斥锁并在满足某个条件时通知线程;这样您就不需要在需要时分配新线程,但如果您希望节省内存,这并不总是一件好事。另一种选择是在需要数据时向另一个协同程序产生协程,这可以说是更漂亮的。您需要自己实现协同程序,或使用现成的库,例如boost.coroutine

实施例

::std::condition_variable cv_;
::std::mutex m_;
bool data_is_ready_{};

StartMyThread()
{
  ::std::thread([this]
    {
      for (;;)
      {
        ::std::unique_lock<decltype(m_)> l(m_);
        cv.wait(l, [this]{ return data_is_ready_; });

        // do your stuff, m_ is locked
        data_is_ready_ = false;
      }
    }
  ).detach();
}

通知:

{
  ::std::unique_lock<decltype(m_)> l(m_);

  data_is_ready_ = true;
}

cv_.notify_one();

因为在通知之前释放锁定通常会更快,反之亦然。