Потокобезопасность в boost::unordered_map для std::string и std::list при внесении изменений в список
Я использую boost::unordered_map<const std::string, std::list<TypeA> >
в критически важной многопоточной среде. Я понимаю, что запись в контейнеры STL не является потокобезопасной, и то же самое относится и к boost::unordered_map
,
boost::unordered_map<const std::string, std::list<TypeA> > myMap;
// Added some elements to myMap
Теперь, если я хочу добавить или удалить элемент типа A в список как, необходимо ли мне просто заблокировать всю карту, а не блокировать изменяемый список, чтобы другие потоки могли читать / записывать остальные пары ключ-значение?
// Assuming there are pair with the keys "Apple" and "Orange" in myMap
A a, b;
myMap["Orange"].push_back(a) //Add an element to the list
myMap["Apple"].remove(b); //Remove an element
Что если список будет заменен другим контейнером STL?
Благодарю.
2 ответа
Поскольку вы изменяете только содержащийся объект, а не саму карту [unordered_], вам нужно только заблокировать этот содержащийся объект. Если вы измените list
для другой последовательности (например, deque или vector) то же самое должно оставаться верным - изменение типа содержащегося объекта не меняет того факта, что вы изменяете только содержащийся объект, а не карту, которая его содержит.
Вам не нужно выполнять какие-либо блокировки здесь. Если гарантировано, что ключи уже существуют, то доступ к ним - это операция без мутаций, которая не требует блокировки (пока никто не мутирует). И каждый список независим - до тех пор, пока никто не получит доступ myMap["Apple"]
в то же время ты золотой. Конечно, вы можете просто использовать что-то более подходящее для задачи, например, список без блокировки, который можно безопасно изменять из нескольких потоков, или concurrent_unordered_map
, такие как вы можете найти в TBB или PPL.