2012-03-07 21 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() (所以不會發生深度複製,這可以避免增長重新分配的問題),您應該可以。

否則你需要同步。

相關問題