В общем, нет. И читателю, и писателю приходится приобретать мьютекс.
В противном случае вы рискуете расами данных при одновременном считывании и записи, что приводит к неопределенному поведению. На практике это может привести к сбоям, или читатели могут получить поврежденные данные, которые вы никогда не помещали на карту. Даже если он работает, он смущает полезные инструменты, такие как детекторы гонок (например, thread sanitizer, Helgrind). Это также делает ваш код потенциально не переносным.
Только если вы можете доказать, что на карте больше нет писателя, и изменения видны для всех остальных потоков, ситуация изменилась, так как теперь все обращения являются читателями. На данный момент не может быть никаких расов данных, и их можно безопасно читать с карты без какой-либо синхронизации.
Если все еще есть возможность обновлений, вы можете использовать параллельные структуры данных, чтобы избежать блокировок. C++ 11 (и C++ 17) не предоставляют один, но существуют нестандартные реализации.
Так что, если вам действительно нужна производительность, вы можете взглянуть на эти параллельных реализаций хэш-карты (в противном случае просто использовать std::unordered_map
в сочетании с взаимной блокировкой для всех обращений):
- Concurrent data structures в Intel Threading Building Блоки (TBB)
- concurrent_unordered_map (подобные
std::unorder_map
, но не поддерживает одновременные операции удаления)
- concurrent_hash_map (также поддерживает удаление Operati дополнения, но интерфейс отличается, поскольку она использует объекты аксессоры)
- Junction (кажется, самый быстрый, но требует, чтобы потоки периодически вызывать операцию очистки, когда он не использует карту. Это делается для восстановления памяти без использования сборщика мусора, как описано в разделе «Безопасная рекультивация памяти» во введении blog post.)