2010-12-15 2 views
0

C++ обеспечивает очень удобный способ, чтобы пересечь контейнер с итерацией,Когда использовать мьютекс с итерацией. C++

for(vector<int>::const_iterator p = c.begin(); p!=c.end();p++){} 

но если когда это проходит, кто-то c.push_back(10).

Разве это сломает петлю?

Должен ли я использовать мьютексы каждый раз, когда использую операцию с контейнером?

Спасибо.

ответ

2

Да, здесь есть состояние гонки.

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

Самый простой способ сделать это - использовать мьютексы.

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

2

Да, вы должны, когда записи возможны из других потоков.

http://www.sgi.com/tech/stl/thread_safety.html

Если несколько потоков доступа один контейнер, и по меньшей мере один поток потенциально может писать, то пользователь несет ответственность за обеспечение взаимного исключения между потоками во время контейнера получает доступ.

1

У вас есть две проблемы. Во-первых, у вас проблема аннулирования итератора. Поскольку push_back увеличивает размер вектора, у него есть возможность вызвать выделение. всякий раз, когда изменяется емкость (не число элементов) вектора, все итераторы в вектор становятся недействительными. Это проще всего решить, убедившись, что вы вызываете reserve() перед началом цикла, чтобы убедиться, что в векторе достаточно места для удовлетворения всех будущих попыток push_back во время цикла.

Другая проблема, как упоминалось в других сообщениях, у вас есть условие гонки, когда вставка может работать одновременно с элементом, к которому осуществляется доступ.

0

Да, вам необходимо защитить весь вектор с помощью мьютекса. И это хорошая причина не использовать векторы для обмена данными между потоками. Большую часть времени мы используем очереди, защищая push/pop с помощью блокировок.

Если вам нужно обмениваться данными с использованием больших буферов, я бы рекомендовал использовать какую-то настраиваемую структуру со «страницами», поэтому вы можете заблокировать только небольшую часть и позволить другим потокам работать в разных местах памяти на в то же время.

0

Самый простой способ для блокировки перед тем итерации и разблокировать после окончания

  1. мьютекс блокировки
  2. Итерация
  3. мьютекс разблокировать
Смежные вопросы