QList, QVector или std::vector многопоточное использование

Я бы хотел, чтобы два потока работали следующим образом:

  • Первый поток добавит значения в вектор
  • Второй поток будет иметь доступ только для чтения к элементам по индексу

Я могу сделать мьютекс и сделать глубокую копию перед началом чтения второго потока.... Но этот способ действительно медленный... Как это можно сделать без мьютекса? Здесь: вектор STL и безопасность потоков Я читал, что можно использовать std:: deque, но это не так, как std::vector...

Где я могу найти контейнер append-only, который не передает данные realloc?

Я решил свою проблему, создав собственный контейнер 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]; 
 }
};
</t></t></std::vector<t></typename></vector>

Безопасно ли мое решение?

3 ответа

Ваше решение не является потокобезопасным без механизма блокировки.

Вы можете использовать tbb:: concurrent_vector или Concurrency:: concurrent_vector для одновременной вставки и доступа. Никакой дополнительной блокировки не требуется. Небезопасно стирать элементы из этих векторов, но с тобой все в порядке.


QList и QVector являются повторными, так что пока вы никогда не читаете последнюю запись, пока поток один активен (так что вы не получите значение mid-write), и всегда используйте at() во втором потоке (так что не происходит глубокой копии, это позволяет избежать проблем с перераспределением роста), вы должны быть в порядке.

В противном случае вам потребуется синхронизация.


Контейнеры STL по умолчанию не обеспечивают потокобезопасность. Для параллельных операций над структурами данных лучше всего обеспечить собственный синхронизированный доступ для обеспечения безопасности потоков.

licensed under cc by-sa 3.0 with attribution.