Какие примитивы синхронизации есть между горутинами в Go
Что проверяют
Знаете ли вы весь набор инструментов, а не только «каналы и мьютекс», и умеете ли выбрать нужный под задачу. Следом почти всегда спрашивают, когда канал лучше мьютекса, и просят найти гонку в коротком куске кода.
Как отвечать
Разделите ответ на две группы: пакет sync с sync/atomic и каналы.
sync.Mutex: эксклюзивный доступ к общему состоянию. Не реентерабельный: повторныйLockиз той же горутины даёт дедлок;sync.RWMutex: много читателей или один писатель. Выигрыш есть, когда чтений заметно больше, чем записей, иначе обычный мьютекс не хуже;sync.WaitGroup: дождаться группы горутин.Addвызывается доgo, а не внутри горутины; с Go 1.25 естьwg.Go(f), который делает это сам;sync.Once: однократная инициализация, с Go 1.21 к нему добавилисьsync.OnceFuncиsync.OnceValue;sync.Cond: ожидание условия несколькими горутинами,Broadcastбудит всех. В прикладном коде встречается редко, обычно его заменяет канал;sync/atomic: счётчики и флаги без блокировки, типыatomic.Int64,atomic.Bool,atomic.Pointer[T];- каналы и
select: передача данных и владения ими, сигнал завершения черезclose, отмена и таймауты черезcontext.Context.
Рядом стоит назвать errgroup из golang.org/x/sync: он ждёт группу горутин, возвращает первую ошибку и отменяет контекст остальных. И упомянуть go test -race для поиска гонок.
Правило выбора: канал, когда передаёте данные или владение ими; мьютекс, когда защищаете состояние внутри структуры.
Где спотыкаются
Копируют структуру с мьютексом по значению, например через метод с ресивером-значением. Копия получает свой замок, защита пропадает, а go vet об этом предупреждает.
Вызывают cond.Wait() без цикла проверки условия. Signal не запоминается: если он пришёл раньше, чем горутина начала ждать, она уснёт навсегда, а после пробуждения условие может уже не выполняться. Поэтому ожидание пишется как for !ready { cond.Wait() } под захваченным мьютексом.
Закрывают канал со стороны получателя или закрывают его дважды. Закрывает тот, кто пишет, а запись в закрытый канал и повторный close вызывают панику.