многопоточность — C ++ доступ к вектору из нескольких потоков

В моей программе запущено несколько потоков. Каждый поток получает указатель на какой-то объект (в моей программе — вектор). И каждый поток изменяет вектор.

И иногда моя программа завершается с ошибкой segm. Я думал, что это произошло, потому что поток A начинает что-то делать с вектором, в то время как поток B не завершил работу с ним? Может ли это быть правдой?

Как я должен это исправить? Синхронизация потоков? Или, может быть, сделать флаг VectorIsInUse и установить этот флаг в true при работе с ним?

3

Решение

vectorКак и все контейнеры STL, не является потокобезопасным. Вы должны явно управлять синхронизацией самостоятельно. std::mutex или же boost::mutex можно использовать для синхронизации доступа к vector,

Не используйте флаг, так как он не является потокобезопасным:

  • Поток А проверяет значение isInUse флаг и это false
  • Поток А приостановлен
  • Поток B проверяет значение isInUse флаг и это false
  • Наборы резьбы B isInUse в true
  • Резьба B подвешена
  • Тема А возобновлена
  • Тема А еще думает isInUse является false и устанавливает его true
  • Нить A и B теперь имеют доступ к vector

Обратите внимание, что каждый поток должен будет заблокировать vector на все время его нужно использовать. Это включает в себя изменение vector и используя vectorитераторы как итераторы могут стать недействительными, если элемент, на который они ссылаются, erase() или vector претерпевает внутреннее перераспределение. Например не делайте:

mtx.lock();
std::vector<std::string>::iterator i = the_vector.begin();
mtx.unlock();

// 'i' can become invalid if the `vector` is modified.
8

Другие решения

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

Вам нужно что-то вроде TBB или PPL, который имеет concurrent_vector в этом.

2

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

0