В моей программе запущено несколько потоков. Каждый поток получает указатель на какой-то объект (в моей программе — вектор). И каждый поток изменяет вектор.
И иногда моя программа завершается с ошибкой segm. Я думал, что это произошло, потому что поток A начинает что-то делать с вектором, в то время как поток B не завершил работу с ним? Может ли это быть правдой?
Как я должен это исправить? Синхронизация потоков? Или, может быть, сделать флаг VectorIsInUse
и установить этот флаг в true при работе с ним?
vector
Как и все контейнеры STL, не является потокобезопасным. Вы должны явно управлять синхронизацией самостоятельно. std::mutex
или же boost::mutex
можно использовать для синхронизации доступа к vector
,
Не используйте флаг, так как он не является потокобезопасным:
isInUse
флаг и это false
isInUse
флаг и это false
isInUse
в true
isInUse
является false
и устанавливает его true
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.
Если вам нужен контейнер, который можно безопасно использовать из множества потоков, вам нужно использовать контейнер, специально разработанный для этой цели. Интерфейс стандартных контейнеров не предназначен для одновременной мутации или любого другого параллелизма, и вы не можете просто заблокировать проблему.
Вам нужно что-то вроде TBB или PPL, который имеет concurrent_vector
в этом.
Вот почему почти каждая библиотека классов, предлагающая потоки, также имеет примитивы синхронизации, такие как взаимные блокировки / блокировки. Вам необходимо настроить один из них и установить / снять блокировку для каждой операции с общим элементом (операции чтения и записи, поскольку необходимо также предотвращать чтение во время записи, а не просто предотвращать одновременную запись нескольких записей).