Ответ
sync.Map
— это специализированная конкурентная структура данных, оптимизированная для двух основных сценариев:
- Кэширование по принципу "записал один раз, читай много раз" (write-once, read-many). Когда ключ добавляется в мапу и после этого в основном только читается, без перезаписи или удаления.
- Высококонкурентный доступ к разным ключам. Когда множество горутин одновременно и независимо друг от друга читают, пишут и удаляют разные ключи.
Как это работает?
sync.Map
достигает эффективности за счет внутреннего устройства: она использует две мапы. Основная, read
, доступна для чтения без блокировок с помощью атомарных операций. Вторая, dirty
, используется для записи и требует мьютекса. Это позволяет множеству читателей работать параллельно без ожидания блокировок, которые требуются только для операций записи.
Когда map + sync.Mutex
лучше?
Обычная мапа с мьютексом будет производительнее в следующих случаях:
- Когда количество чтений и записей примерно одинаково.
- Когда существует высокая конкуренция за одни и те же ключи.
- Когда мапа инициализируется один раз и далее не изменяется (в этом случае даже мьютекс не нужен для чтения).
- Когда производительность критична, и накладные расходы
sync.Map
(например,interface{}
в качестве типа значения) неприемлемы.
Вывод: sync.Map
— это не замена map + Mutex
по умолчанию, а оптимизация для специфичных нагрузок. Всегда выбирайте решение на основе профилирования вашего приложения.