STL вектор и потокобезопасность - PullRequest
12 голосов
/ 03 декабря 2010

Допустим, у меня есть вектор из N элементов, но до n элементов этого вектора имеют значимые данные.Один поток обновлений обновляет n-й или n + 1-й элемент (затем устанавливает n = n + 1), также проверяет, слишком ли n слишком близко к N, и при необходимости вызывает vector :: resize (N + M).После обновления поток вызывает несколько дочерних потоков, чтобы прочитать до n-ых данных и выполнить некоторые вычисления.

Гарантируется, что дочерние потоки никогда не изменяют и не удаляют данные (фактически никакие данные не удаляются), а программа обновления вызывает дочерние процессы сразу после завершения обновления.

Пока что никаких проблем не возникало, но я хочу спросить, может ли проблема возникнуть при перераспределении вектора в больший блок памяти, если после предыдущего обновления осталось несколько дочерних рабочих потоков.
Илибезопасно ли использовать vector, так как он не является потокобезопасным, в таком многопоточном случае?

EDIT: поскольку только вставка происходит, когда средство обновления вызывает vector :: resize (N + M, 0),Есть ли возможные варианты решения моей проблемы?Из-за высокой производительности вектора STL я не хочу заменять его на блокируемый вектор, или в этом случае существуют какие-либо производные, известные и свободные от блокирования векторы?

Ответы [ 3 ]

20 голосов
/ 03 декабря 2010

Я хочу спросить, может ли возникнуть проблема при перераспределении вектора в больший блок памяти, если после предыдущего обновления осталось несколько дочерних рабочих потоков.

Да, этобыло бы очень плохо.

Если вы используете контейнер из нескольких потоков, и хотя бы один поток может выполнить какое-либо действие, которое может изменить состояние контейнера, доступ к контейнеру должен быть синхронизирован.

В случае std::vector все, что изменяет его размер (в частности, вставки и стирания), меняет свое состояние, даже если перераспределение не требуется (любая вставка или стирание требует внутреннего размера std::vectorданные бухгалтерского учета, подлежащие обновлению).


Одним из решений вашей проблемы было бы то, чтобы производитель динамически выделил std::vector и использовал std::shared_ptr<std::vector<T> > для его владения и передавал std::shared_ptr каждому

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

1 голос
/ 03 декабря 2010

Как ваши работники решили работать с потоком данных безопасно? Есть ли какая-то сигнализация между работниками и продюсером? Если нет, то, безусловно, существует проблема, из-за которой производитель может заставить вектор двигаться, пока он еще работает. Хотя это можно легко исправить, перейдя на std::deque (обратите внимание, что std::deque делает недействительными итераторы на push_back, но ссылки на элементы не затрагиваются).

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

Я сделал свой собственный GrowVector.Это работает для меня, и это действительно быстро.

Ссылка: QList, QVector или std :: vector многопоточность

...