简体   繁体   English

了解使用std :: condition_variable的示例

[英]Understanding the example of using std::condition_variable

There is example of using condition_variable taken from cppreference.com : 有一个使用来自cppreference.com的 condition_variable例子:

#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>
#include <queue>
#include <chrono>

int main()
{
    std::queue<int> produced_nums;
    std::mutex m;
    std::condition_variable cond_var;
    bool done = false;
    bool notified = false;

    std::thread producer([&]() {
        for (int i = 0; i < 5; ++i) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            std::lock_guard<std::mutex> lock(m);
            std::cout << "producing " << i << '\n';
            produced_nums.push(i);
            notified = true;
            cond_var.notify_one();
        }   

        std::lock_guard<std::mutex> lock(m);  
        notified = true;
        done = true;
        cond_var.notify_one();
    }); 

    std::thread consumer([&]() {
        while (!done) {
            std::unique_lock<std::mutex> lock(m);
            while (!notified) {  // loop to avoid spurious wakeups
                cond_var.wait(lock);
            }   
            while (!produced_nums.empty()) {
                std::cout << "consuming " << produced_nums.front() << '\n';
                produced_nums.pop();
            }   
            notified = false;
        }   
    }); 

    producer.join();
    consumer.join();
}

If variable done comes true before the consumer thread is started, the consumer thread will not get any message. 如果在启动使用者线程之前变量done变为true ,则使用者线程将不会获得任何消息。 Indeed, sleep_for(seconds(1)) almost avoids such situation, but could it be possible in theory (or if don't have sleep in code)? 实际上, sleep_for(seconds(1))几乎避免了这种情况,但理论上是否可能 (或者如果代码中没有sleep )?

In my opinion correct version should look like this to force running consumer loop at least once: 在我看来,正确的版本应该像这样强制运行消费者循环至少一次:

std::thread consumer([&]() {
    std::unique_lock<std::mutex> lock(m);
    do {
        while (!notified || !done) {  // loop to avoid spurious wakeups
            cond_var.wait(lock);
        }   

        while (!produced_nums.empty()) {
            std::cout << "consuming " << produced_nums.front() << '\n';
            produced_nums.pop();
        }   

        notified = false;
    } while (!done);
}); 

Yes, you are absolutely right: there is a (remote) possibility that the consumer thread will not start running until after done has been set. 是的,你是绝对正确的:有一种(远程)可能性,消费者线程在done设置之后才会开始运行。 Further, the write to done in the producer thread and the read in the consumer thread produce a race condition, and the behavior is undefined. 此外,写done的生产者线程和消费者线程读取产生竞争条件,而行为是不确定的。 Same problem in your version. 您的版本中的问题相同。 Wrap the mutex around the entire loop in each function. 每个函数中围绕整个循环包装互斥锁。 Sorry, don't have the energy to write the correct code. 对不起,没有精力写出正确的代码。

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

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