2012-03-07 675 views
2

我想两个线程的工作是这样的:的QList,QVector或std :: vector的多线程使用

  1. 第一个线程将追加值向量
  2. 第二个线程将有只读元素的访问权限以索引

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

我在哪里可以找到只附加容器,不重新分配数据?添加元素来支持,获得大小,通过索引访问元素:


我已经用行动创造自己的容器GrowVector解决我的问题。它适用于默认值为2Billion的元素,但可以通过构造函数参数进行更改。

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

我的解决方案是否安全?

+2

如果从多个线程使用标准库容器并且至少有一个线程正在修改容器,则必须同步对容器的访问。所有标准库容器都是这种情况,而不仅仅是'vector'。 – 2012-03-07 07:09:30

+0

不重新分配内存的唯一方法是如果你已经知道向量中的最大条目数量,然后使用'reserve'。或者'std :: array',如果你知道编译时已经有了大小。也许你想要一个'std :: list'而不是? – 2012-03-07 07:15:34

回答

1

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

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

+0

谢谢。 TBB的concurrent_vector看起来像我所需要的。 – k06a 2012-03-07 11:14:51

2

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

3

QListQVector是重入,所以只要你不读的最后一项,而一个线程是活动的(这样你就不会得到一个值,中间写),并且总是在第二个线程使用at() (所以不会发生深度复制,这可以避免增长重新分配的问题),您应该可以。

否则你需要同步。