生产者消费者实现中的条件变量应如何初始化

How should conditional variables in producer-consumer implementations be initialized

本文关键字:初始化 变量 条件 消费者 实现 生产者      更新时间:2023-10-16

我正在尝试了解条件变量实现生产者消费者缓冲区。我有以下代码,该代码实现了整数的队列(可能是Linux文件描述符)。该代码按预期工作,但我试图理解原因。在向其他条件变量发出信号之前,对方和Dequeue操作都在某个条件变量上等待。为什么这些等待不受阻碍?这是由于虚假的唤醒吗?

#include <iostream>
#include <thread>
#include <list>
#include <mutex>
#include <chrono>
#include <condition_variable>
using namespace std::chrono_literals;
using std::cout;
using std::endl;
class FDQueue
{
    std::mutex _mutex;
    std::condition_variable _notEmptyCv, _notFullCv;
    std::list<int> _fds;
    size_t _maxSize;
public:
    void add(int fd) {
        std::unique_lock<std::mutex> locker(this->_mutex);
        this->_notFullCv.wait(locker, [this](){return this->_fds.size() < this->_maxSize;});
        cout<<"Enqueue "<<endl;
        this->_fds.push_back(fd);
        locker.unlock();
        this->_notEmptyCv.notify_one();
    }
    int remove() {
        std::unique_lock<std::mutex> locker(_mutex);
        this->_notEmptyCv.wait(locker, [this](){return this->_fds.size() > 0;});
        int fd = this->_fds.front();
        this->_fds.pop_front();
        cout<<"Dequeue"<<endl;
        locker.unlock();
        this->_notFullCv.notify_all();
        return fd;
    }
    FDQueue(size_t maxSize) : _maxSize(maxSize) {}
};
FDQueue queue(5);
void producer() {
    while (true) {
        queue.add(0);
        std::this_thread::sleep_for(2s);
    }
}
void consumer() {
    while (true) {
        queue.remove();
    }
}
int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
}

在_notfullcv上添加等待,然后在_notemptycv上删除等待。这些如何 有条件的变量第一次发出信号?

他们没有。如果您查看文档,那么接受锁定l和谓词predstd::condition_variable::wait的过载实际上是...

while (!pred())
  wait(l);

在您的情况下,重要的部分是在等待之前检查了条件。因此,第一个呼叫add会发现队列不满,并且不会拨打std::condition_variable::wait(没有谓词)。