c++11 - C++ 11 condition_variable等待虚假唤醒不起作用

标签 c++11 condition-variable

我尝试使用condition_variable编写一个简单的生产者/消费者,

include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
#include <chrono>
using namespace std;

condition_variable cond_var;
mutex m;
int main()
{
    int c = 0;
    bool done = false;
    cout << boolalpha;
    queue<int> goods;

    thread producer([&](){
        for (int i = 0; i < 10; ++i) {
            m.lock();
            goods.push(i);
            c++;
            cout << "produce " << i << endl;
            m.unlock();
            cond_var.notify_one();
            this_thread::sleep_for(chrono::milliseconds(100));
        }
        done = true;
        cout << "producer done." << endl;
        cond_var.notify_one();
    });

    thread consumer([&](){
        unique_lock<mutex> lock(m);
        while(!done || !goods.empty()){
            /*
            cond_var.wait(lock, [&goods, &done](){
                        cout << "spurious wake check" << done <<endl;
                        return (!goods.empty() || done);
            });
            */  
            while(goods.empty())
            {
                cout<< "consumer wait" <<endl;
                cout<< "consumer owns lock " << lock.owns_lock() <<endl;
                cond_var.wait(lock);
            }
            if (!goods.empty()){
                cout << "consume " << goods.front()<<endl;
                goods.pop();
                c--;
            }
        }
    });

    producer.join();
    consumer.join();
    cout << "Net: " << c << endl;
}

我现在遇到的问题是,当消费者消费完生产者将done设置为true之前的最后一个项目时,消费者线程将卡在

 while(goods.empty())
            {
                cout<< "consumer wait" <<endl;
                cout<< "consumer owns lock " << lock.owns_lock() <<endl;
                cond_var.wait(lock);
            }

我的理解是 cond_var.wait(lock) 会虚假唤醒,从而退出 while(good.empty()) 循环,但情况似乎并非如此?

最佳答案

虚假唤醒并不经常发生,您可以依靠它以您建议的方式打破循环。发生虚假唤醒的风险是当前条件变量实现的一个不幸的副作用,您必须考虑这一点,但不能保证您何时(如果有)会经历虚假唤醒。

如果您想确保使用者线程不会陷入等待永远不会到来的通知的状态,您可以尝试使用 std::condition_variable::wait_for() 来代替。它需要一个持续时间,如果持续时间到期,将会超时并重新获取锁。它可能被视为更接近繁忙等待,但如果超时足够长,对性能的影响应该可以忽略不计。

关于c++11 - C++ 11 condition_variable等待虚假唤醒不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49571276/

相关文章:

c++ - 为什么构造函数在使用 CHAR 类型的参数调用时选择类型 INT 而不是 SHORT?

c++ - 在使用 stop_token 等待条件变量_any 时是否需要拥有锁来请求停止?

c - 使用 pthread_cond_wait 和 pthread_cond_signal 保证 yield

c++ - 条件变量 - 为什么在调用 pthread_cond_wait() 之前调用 pthread_cond_signal() 是一个逻辑错误?

c++ - 缓冲区填充不同类型的数据,并严格别名

c++ - 预期 { 在析构函数之前

c++ - const constexpr char* 与 constexpr char*

c++ - 在引用初始化中使用已删除的复制构造函数进行复制初始化

multithreading - 条件变量真的需要另一个变量吗?

multithreading - pthread_cond_timedwait 超时后线程是否拥有互斥锁?