Все темы К задачам
Тема 02
Синхронизация и sync
Разберись в теме, затем проверь понимание на задачах.
0/4 решено0%
О чём этот блок
Каналы хороши, когда данные движутся от одной горутины к другой. Но счётчик запросов,
кэш, флаг «инициализация выполнена» никуда не движутся: они лежат на месте, а к ним
обращаются сотни горутин. Для такого общего состояния есть пакеты sync и sync/atomic.
Блок учит не только защищать данные, но и выбирать инструмент. Счётчик можно защитить
мьютексом или атомиком, кэш — Mutex, RWMutex или неизменяемыми снимками через
atomic.Value. Что быстрее, зависит от доли чтений, размера критической секции и
числа ядер, поэтому выбор подтверждают бенчмарком, а не привычкой.
Что понадобится
sync.Mutexи правило «все обращения к общим данным — под одной блокировкой».sync.RWMutexдля нагрузки, где чтений намного больше, чем записей.atomic.Int64и разница между неделимой операцией и неделимой последовательностью операций.sync.Once: ровно один запуск и общий результат для всех ожидающих.sync.Condи проверка условия в цикле.- Happens-before: почему без синхронизации запись одной горутины может быть не видна другой.
Задачи
- 05 · Thread-safe Counter (Mutex vs atomic) — две реализации одного счётчика и их цена при тысячах горутин.
- 06 · Потокобезопасный кэш (95% reads) —
RWMutexпротивMutexпод нагрузкой, где почти все обращения — чтения. - 07 · Idempotent Initializer (sync.Once) — инициализация выполняется один раз, и все вызывающие получают один результат, включая ошибку.
- 08 · WaitGroup своими руками — свой аналог
WaitGroupна мьютексе иsync.Cond, безsync.WaitGroupиatomic.
Что прочитать
- sync: Mutex, RWMutex, Once, Cond, WaitGroup, Pool — каждый примитив, его гарантии и типичные ошибки.
- sync/atomic — атомики против мьютекса, конкуренция за ячейку, CAS.
- Модель памяти и happens-before — почему всё это вообще нужно.
// Идиома блока: читатели не мешают друг другу, писатель — один.
func (c *Cache) Get(k string) (any, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
v, ok := c.m[k]
return v, ok
}