QList, QVector или std :: vector многопоточное использование - PullRequest
2 голосов
/ 07 марта 2012

Я бы хотел, чтобы две темы работали так:

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

Я могу сделать мьютекс и сделать глубокое копирование до начала чтения второго потока .... Но этот путь действительно медленный ... Как можно сделать это без мьютекса? Здесь: STL вектор и потокобезопасность Я читал, что можно использовать 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 ]

3 голосов
/ 07 марта 2012

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

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

2 голосов
/ 07 марта 2012

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

1 голос
/ 07 марта 2012

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

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

...