Ответ
Пакет sync
предоставляет примитивы синхронизации, которые используются для управления конкурентным доступом к общим ресурсам из нескольких горутин и для координации их работы. Его главная цель — предотвращение состояния гонки (data race).
Основные примитивы:
-
sync.Mutex
(Mutual Exclusion) — обеспечивает эксклюзивный доступ к критической секции кода. Только одна горутина может владеть мьютексом в любой момент времени.var mu sync.Mutex mu.Lock() // Блокирует доступ для других горутин // ... критическая секция ... mu.Unlock() // Освобождает блокировку
-
sync.RWMutex
(Read/Write Mutex) — более гранулярная блокировка. Позволяет любому количеству горутин одновременно читать данные, но запись возможна только при эксклюзивной блокировке. Идеален для данных, которые читаются гораздо чаще, чем изменяются. -
sync.WaitGroup
— позволяет дождаться завершения работы группы горутин. Основные методы:Add()
для увеличения счетчика горутин,Done()
для его уменьшения (вызывается в конце работы горутины) иWait()
для блокировки до тех пор, пока счетчик не станет равен нулю.var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) // Увеличиваем счетчик go func() { defer wg.Done() // Уменьшаем счетчик при выходе из горутины // ... полезная работа ... }() } wg.Wait() // Ожидаем, пока все горутины завершатся
-
sync.Once
— гарантирует, что определенный участок кода будет выполнен только один раз за все время работы программы, независимо от количества вызовов. Часто используется для ленивой инициализации (например, синглтонов). -
sync.Pool
— предоставляет кеш временных объектов для повторного использования, что помогает снизить нагрузку на сборщик мусора (GC) в высокопроизводительных приложениях. -
sync.Map
— потокобезопасный аналогmap
, оптимизированный для сценариев, где ключи в основном читаются или обновляются, но редко добавляются новые.