У меня есть программа C++ 11, которая выполняет некоторые вычисления и использует std::unordered_map
для кэширования результатов этих вычислений. Программа использует несколько потоков, и они используют общий unordered_map
для хранения и совместного использования результатов вычислений.Гонка данных с std :: unordered_map, несмотря на блокировку вставки с мьютексом
Основываясь на моем чтении unordered_map
и STL контейнеров спецификации, а также unordered_map thread safety, кажется, что unordered_map
, разделяемые несколькими потоками, может обрабатывать одну нить писать в то время, но многие читатели в то время.
Поэтому я использую std::mutex
для переноса моих insert()
звонков на карту, так что не более одного потока вставляется одновременно.
Однако мои звонки find()
не имеют мьютекса, так как из моего чтения кажется, что многие потоки должны быть в состоянии читать сразу. Тем не менее, я иногда получаю данные рас (как было обнаружено TSAN), проявляясь в SEGV. Гонка данных четко указывает на вызовы insert()
и find()
, о которых я упоминал выше.
Когда я обертываю вызовы find()
в мьютексе, проблема исчезает. Тем не менее, я не хочу сериализовать параллельные чтения, поскольку я пытаюсь сделать эту программу как можно быстрее. (FYI: я бегу с использованием gcc 5.4.)
Почему это происходит? Является ли мое понимание гарантий параллельности для std::unordered_map
неверным?
Похоже, вам нужен 'shared_mutex', поскольку для всех запросов на запись и чтение требуется синхронизация, так как у вас есть писатель. – NathanOliver
Ответ в связанном потоке гласит: «* A. Одновременное чтение нескольких потоков * ** или ** * B. Один поток, записывающий одновременно *. Обратите внимание на ** или **. – Pixelchemist
Вы неправильно истолковали спецификацию; он позволяет нескольким считывателям, но не нескольким читателям, независимо от одного писателя. Вам нужен блокиратор с несколькими читателями/одиночными писателями, например, shared_mutex, упомянутый в комментарии NathanOliver. – antlersoft