简体   繁体   English

如何正确使用std :: condition_variable?

[英]How to use a std::condition_variable correctly?

I'm confused about conditions_variables and how to use them (safely). 我对conditions_variables以及如何使用它们(安全)感到困惑。 In my application I've a class that makes a gui-thread but while the gui is constructed by the gui-thread, the main thread needs to wait. 在我的应用程序中,我有一个创建gui线程的类,但是当gui由gui-thread构造时,主线程需要等待。

The situation is the same as for the function below. 情况与下面的功能相同。 The main thread makes a mutex, lock and condition_variable . 主线程产生互斥锁,锁和condition_variable It then makes the thread. 然后它成为线程。 While this worker thread has not passed a certain point (here printing the numbers), the main thread is not allowed to continue (ie has to wait for all numbers being printed). 虽然此worker thread尚未通过某一点(此处打印数字),但主线程不允许继续(即必须wait所有正在打印的数字)。

How do I use condition_variables correctly in this context? 如何在此上下文中正确使用condition_variables Also, I've read that spontaneous wake-ups are an issue. 此外,我读过自发的唤醒是一个问题。 How can I handle them? 我怎么处理它们?

    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();
    }

Typically you'd have some observable shared state on whose change you block: 通常,您有一些可观察的共享状态,您可以阻止其更改:

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();
}

Note that you wait in a loop until the actual condition is met. 请注意,您在循环中等待,直到满足实际条件。 Note also that access to the actual shared state ( done ) is serialized via the mutex done_mx , which is locked whenever done is accessed. 另请注意,通过互斥锁done_mx序列化对实际共享状态( done )的访问,该互斥锁在访问done时被锁定。

There's a helper member function that performs the condition check for you so you don't need the loop: 有一个帮助成员函数,它为您执行条件检查,因此您不需要循环:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM