问题描述
我试图理解使用条件变量来实现生产者-消费者缓冲区.我有以下代码,该代码实现了整数队列(可能是linux文件描述符).该代码按预期工作,但我试图理解原因.入队和出队操作都在通知另一个条件变量之前先等待某个条件变量.这些等待为何畅通无阻?这是由于虚假唤醒引起的吗?
I am trying to understand the use of conditional variables to implement producer-consumer buffers. I have the following code, which implements a queue for integers (which could be linux file descriptors). The code works as expected, but I am trying to understand why. Both enqueue and dequeue operations wait on some conditional variable before signaling the other conditional variable. Why are these waits unblocking? Is this due to spurious wakeups?
#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();
}
推荐答案
他们没有.如果您查看文档,则 std的重载接受锁
有效地实现为... l
和谓词 pred
的:: condition_variable :: wait
They don't. If you look at the documentation, the overload of std::condition_variable::wait
that accepts a lock l
and predicate pred
is effectively implemented as...
while (!pred())
wait(l);
您情况下的重要部分是在等待之前 检查条件.因此,第一次调用 add
会发现队列未满,并且不会调用 std :: condition_variable :: wait
(不带谓词).
The important part in your case being that the condition is checked before waiting. Hence, the first call to add
will find the queue not full and no call to std::condition_variable::wait
(without a predicate) will be made.
这篇关于生产者-消费者实现中的条件变量应如何初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!