QList,QVector或std :: vector多线程用法

时间:2012-03-07 07:02:00

标签: c++ multithreading qt thread-safety containers

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

  1. 第一个帖子会将值附加到vector
  2. 第二个线程将按索引
  3. 对元素进行只读访问

    我可以在第二个线程开始读取之前制作互斥并进行深度复制....但这种方式真的很慢......如何在没有互斥的情况下制作它?在这里:STL vector and thread-safety 我读过可以使用std :: deque,但它失败了,就像std :: vector ...

    哪里可以找到仅附加容器,哪些不重新分配数据?


    我通过创建自己的容器GrowVector来解决我的问题:操作:向后添加元素,获取大小,按索引访问元素。它适用于默认的2亿个元素,但可以通过构造函数参数进行更改。

    #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];    
        }
    };
    

    我的解决方案安全吗?

3 个答案:

答案 0 :(得分:3)

QListQVector是可重入的,所以只要您从未读过最后一个条目,而第一个线程处于活动状态(因此您不会在写入中间获得值),并且总是在第二个线程中使用at()(因此不会发生深层复制,这可以避免增长重新分配的问题)你应该没问题。

否则你需要同步。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

您可以同时使用tbb::concurrent_vectorConcurrency::concurrent_vector进行多次插入和访问。无需额外锁定。从这些矢量中删除元素是不安全的,但我猜你也没问题。