我正在尝试使用 Qt 的并发线程构造创建一个并发队列。
#ifndef CONCURRENTQUEUE_H
#define CONCURRENTQUEUE_H
#include <QMutex>
#include <QWaitCondition>
#include <queue>
template<typename Data>
class ConcurrentQueue
{
private:
std::queue<Data> the_queue;
QMutex the_mutex;
QWaitCondition the_condition_variable;
bool closed;
public:
void setClosed(bool state)
{
QMutexLocker locker(&the_mutex);
closed = state;
}
bool getClosed()
{
QMutexLocker locker(&the_mutex);
return closed;
}
void push(Data const& data)
{
QMutexLocker locker(&the_mutex);
the_queue.push(data);
the_condition_variable.wakeOne();
}
bool empty()
{
QMutexLocker locker(&the_mutex);
return the_queue.empty();
}
bool try_pop(Data& popped_value)
{
QMutexLocker locker(&the_mutex);
if(the_queue.empty())
{
return false;
}
popped_value = the_queue.front();
the_queue.pop();
return true;
}
void wait_and_pop(Data& popped_value)
{
QMutexLocker locker(&the_mutex);
while(the_queue.empty())
{
the_condition_variable.wait(&the_mutex);
}
popped_value = the_queue.front();
the_queue.pop();
the_condition_variable.wakeOne();
}
//created to allow for a limited queue size
void wait_and_push(Data const& data, const int max_size)
{
QMutexLocker locker(&the_mutex);
while(the_queue.size() >= max_size)
{
the_condition_variable.wait(&the_mutex);
}
the_queue.push(data);
the_condition_variable.wakeOne();
}
};
#endif // CONCURRENTQUEUE_H
我的生产者线程使用 wait_and_push 方法将数据插入队列,我一直在尝试让我的消费者使用 try_pop 从队列中读取数据
while(!tiles->empty() || !tiles->getClosed())
{
if(!tiles->try_pop(tile))
continue;
//do stuff with the tile
}
然而,这有时会出现死锁。生产者将关闭的 bool 值设置为消费者线程的标志,表明它已完成加载队列。我的消费者只有这样才能知道队列是正在加载、仍在进行中还是尚未启动。
生产者有一个“wait_and_push”而不是使用正常推送的原因是因为我希望能够使该线程阻塞直到一些项目被处理以避免占用太多内存,并做不必要的磁盘 I/哦。
谁能告诉我哪里出了问题?
最佳答案
你忘了添加
the_condition_variable.wakeOne();
在 try_pop
中。
如果将有多个生产者/消费者访问您的队列,您应该为生产者和消费者分别设置一个QWaitCondition
,否则wakeOne
可能无法唤醒正确的线程。
编辑:
如果将有多个生产者/消费者,那么您应该有一个 notFullCondvar
和一个 notEmptyCondvar
。
try_pop
方法唤醒notFullCondvar
。wait_and_pop
方法等待notEmptyCondvar
,但唤醒notFullCondvar
。push
方法唤醒notEmptyCondvar
。wait_and_push
方法等待notFullCondvar
,但唤醒notEmptyCondvar
。
我希望这是有道理的。
关于c++ - 使用Qt的并发队列是死锁的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7110709/