如何正确使用 std::condition_variable

How to use a std::condition_variable correctly?

本文关键字:condition variable std 何正确      更新时间:2023-10-16

我对conditions_variables以及如何(安全地(使用它们感到困惑。在我的应用程序中,我有一个制作 gui 线程的类,但是虽然 gui 是由 gui 线程构造的,但主线程需要等待。

情况与下面的功能相同。主线程制作互斥锁、锁定和condition_variable。然后它使线程。虽然此worker thread尚未通过某个点(此处打印数字(,但不允许主线程继续(即必须wait打印的所有数字(。

在这种情况下,如何正确使用condition_variables?另外,我读到自发醒来是一个问题。我该如何处理它们?

    int main()
    {
        std::mutex mtx;
        std::unique_lock<std::mutex> lck(mtx);
        std::condition_variable convar;
        auto worker = std::thread([&]{
            /* Do some work. Main-thread can not continue. */
            for(int i=0; i<100; ++i) std::cout<<i<<" ";
            convar.notify_all(); // let main thread continue
            std::cout<<"nworker done"<<std::endl;       
        });

        // The main thread can do some work but then must wait until the worker has done it's calculations.
        /* do some stuff */
        convar.wait(lck);
        std::cout<<"nmain can continue"<<std::endl; // allowed before worker is entirely finished
        worker.join();
    }
通常,

您会有一些可观察的共享状态,阻止其更改:

bool done = false;
std::mutex done_mx;
std::condition_variable done_cv;
{
  std::unique_lock<std::mutex> lock(done_mx);
  std::thread worker([&]() {
    // ...
    std::lock_guard<std::mutex> lock(done_mx);
    done = true;
    done_cv.notify_one();
  });
  while (true) { done_cv.wait(lock); if (done) break; }
  // ready, do other work
  worker.join();
}

请注意,您将在循环中等待,直到满足实际条件。还要注意,对实际共享状态(done(的访问是通过互斥done_mx序列化的,每当访问done时,互斥锁就会被锁定。

有一个帮助程序成员函数可以为您执行条件检查,因此您不需要循环:

done_cv.wait(lock, [&]() { return done; });