c++ - 使用Qt的并发队列是死锁的

标签 c++ multithreading qt queue

我正在尝试使用 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/

相关文章:

c++ - 如何在 OSX 上使用 C++ 中的 CGEventPost 保持按键按下?

C++ 继承 - 为什么调用父方法?

c++ - 桶排序实现

未找到 QtVLC 插件

c++ - MoSync C++ 跨平台开发

c# - 应该异步执行对 NetworkStream 的写入

ios - NSURLCache 线程安全吗?

qt - 如何在 Qt 中从 QToolBar 自定义 QToolButtons?

c++ - 在 qt DOM xml 解析器中使用 setContent(&file) 加载较大文件时出错

java - 试图在 Java 中制作一个模态 "Generating Report"对话框