正确的暂停方式恢复一个std :: thread [英] Correct way to pause & resume an std::thread

查看:442
本文介绍了正确的暂停方式恢复一个std :: thread的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using an std::thread in my C++ code to constantly poll for some data & add it to a buffer. I use a C++ lambda to start the thread like this:

StartMyThread() {

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

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

thread_running is an atomic<bool> declared in class header. Here is my GetData function:

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

下一步我还有一个 StopMyThread 函数,其中将 thread_running 设置为false,以便它退出 lambda块

Next I also have a StopMyThread function where I set thread_running to false so that it exits out of the while loop in the lambda block.

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

效果很好。线程启动&停止而不会崩溃。

It works well. The thread starts & stops without crashing.

此C ++代码在iOS,Android,OS X和Windows上使用。我的应用程序用户界面有一个按钮,要求我启动&停止按下按钮时的线;此按钮在某些情况下可以经常使用。我可以在停止或启动线程时看到UI的瞬间延迟。

This C++ code is used on iOS, Android, OS X and Windows. My application UI has a button which requires me to start & stop the thread on a button press; this button can be frequently used in some occasions. I can see a split second delay in UI while stopping or starting the thread.

我的问题是: 在C ++中,这是正确地启动/停止线程的正确方法?我认为,使用这种逻辑,我每次都会创建一个新线程。据我了解,创建新线程使操作系统分配大量新资源,这可能会占用大量时间。我认为这是我的错误。如何避免这种情况?

My question is: In C++, is this a correct way to start/stop a thread frequently ? I think that with this logic I am creating a new thread every-time. And as I understand, creating a new thread makes the OS allocate lot of new resources which can be time-consoming. And I think this is the mistake I am doing. How can I avoid this ?

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

How can make use of the same thread without allocating new one repeatedly throughout the application lifecycle, and just play/pause it when required ?

推荐答案

这是使用条件变量的经典示例。您等待互斥量,并在满足特定条件时通知线程。这样,您不需要在需要时分配新线程,但是如果您想节省内存,这并不总是一件好事。一种替代方法是在需要数据时将协程生成为另一个协程,这可能更漂亮。您需要自己实现协程,或使用现成的库,例如 boost.coroutine

This is the classical example for the use of a condition variable. You wait on a mutex and notify a thread when a certain condition is fulfilled; this way you don't need to allocate a new thread when you need one, but this is not always a good thing, if you wish to save memory. An alternative would be a coroutine yielding to another coroutine when data is needed, which is arguably prettier. You need to implement coroutines yourself, or use a ready-made library, such as 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();

因为在通知之前释放锁通常比反过来更快。

As it is often faster to free the lock before notifying, than vice-versa.

这篇关于正确的暂停方式恢复一个std :: thread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆