QList、QVector或std::vector多线程使用

QList, QVector or std::vector multi-threaded usage

本文关键字:vector 多线程 std QVector QList      更新时间:2023-10-16

我希望两个线程像这样工作:

  1. 第一个线程将把值附加到向量
  2. 第二个线程将按索引对元素进行只读访问

我可以在第二个线程开始读取之前创建互斥并进行深度复制。。。。但这种方式真的很慢。。。没有互斥体怎么可能做到这一点?这里:STL矢量和线程安全我读到可以使用std::deque,但它像std::vector一样失败。。。

在哪里我可以找到只追加的容器,而不是realloc数据?


我已经通过创建自己的容器GrowVector解决了我的问题,该容器包含以下操作:向后面添加元素、获取大小、按索引访问元素。默认情况下,它适用于20亿个元素,但可以通过构造函数参数进行更改。

#include <vector>
template<typename T>
class GrowVector
{
    std::vector<std::vector<T> > m_data;
    size_t m_size;
public:
    GrowVector(int chunks = 32768)
        : m_data()
        , m_size(0)
    {
        m_data.reserve(chunks);
        m_data.push_back(std::vector<T>());
        m_data.back().reserve(1 << 16);
    }
    void add(const T & value)
    {
        if (m_data.back().size() == m_data.back().capacity())
        {
            m_data.push_back(std::vector<T>());
            m_data.back().reserve(1 << 16);
        }
        m_data.back().push_back(value);
        m_size++;
    }
    size_t size() const
    {
        return m_size;
    }
    T & operator [] (int i)
    {
        return m_data[i >> 16][i & 0xffff]; 
    }
    const T & operator [] (int i) const
    {
        return m_data[i >> 16][i & 0xffff];    
    }
};

我的解决方案安全吗?

QListQVector是可重入的,所以只要在线程一处于活动状态时从不读取最后一个条目(这样在写入过程中就不会得到值),并且总是在第二个线程中使用at()(这样就不会发生深度复制,这样就避免了增长重新分配的问题),那么应该是可以的

否则,您需要同步。

STL容器默认情况下不提供线程安全。对于数据结构上的并发操作,最好提供自己的同步访问,以满足线程安全操作的要求。

如果没有锁定机制,您的解决方案就不是线程安全的。

您可以使用tbb::concurrent_vector或concurrent::concurrent_vector同时进行多个插入和访问。无需额外锁定。从这些向量中删除元素是不安全的,但我想你可以接受。