Когда использовать мьютекс с итерацией.C ++ - PullRequest
0 голосов
/ 16 декабря 2010

C ++ обеспечивает очень удобный способ обхода контейнера с итерацией,

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

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

Разорвет ли он цикл?

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

Спасибо.

Ответы [ 5 ]

2 голосов
/ 16 декабря 2010

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

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

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

2 голосов
/ 16 декабря 2010

Да, здесь есть условие гонки.

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

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

Другим вариантом будет поиск или реализация поточно-ориентированного контейнера, обеспечивающего необходимые вам возможности.

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

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

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

0 голосов
/ 06 апреля 2012

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

  1. блокировка мьютекса
  2. Итерация
  3. разблокировка мьютекса
0 голосов
/ 16 декабря 2010

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

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

...