了解使用std :: condition_variable的示例 [英] Understanding the example of using std::condition_variable

查看:192
本文介绍了了解使用std :: condition_variable的示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个使用 condition_variable 的例子,取自 cppreference.com

There is example of using condition_variable taken from cppreference.com:

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

如果变量 done 在消费者线程启动之前, true ,消费者线程将不会收到任何消息。事实上, sleep_for(seconds(1))几乎避免了这种情况,但可能在理论上(或如果没有 sleep in code)?

If variable done comes true before the consumer thread is started, the consumer thread will not get any message. Indeed, sleep_for(seconds(1)) almost avoids such situation, but could it be possible in theory (or if don't have sleep in code)?

在我看来,正确的版本应该像这样强制运行消费者循环至少一次: / p>

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


推荐答案

是的,你是绝对正确的:远程)可能性,消费者线程将不会开始运行,直到 done 已设置。此外,在生产者线程中对 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. 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. 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.

这篇关于了解使用std :: condition_variable的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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