Пакет sync

14 вопросов

Пакет sync предоставляет примитивы синхронизации: Mutex, RWMutex, WaitGroup, Once, Pool. Необходимы для безопасной работы с общими данными из нескольких горутин.

1 Для чего нужен sync.Mutex? 🟢 Лёгкий
Ответ: B) Защиты общих данных от data race

Мьютекс обеспечивает взаимное исключение: только одна горутина может держать блокировку. mu.Lock() / mu.Unlock() защищают критическую секцию. Типичный паттерн: mu.Lock(); defer mu.Unlock().

Подробнее →
2 Что делает sync.WaitGroup? 🟢 Лёгкий
Ответ: B) Ожидает завершения набора горутин

WaitGroup - счётчик горутин. Add(n) увеличивает счётчик, Done() уменьшает на 1 (обычно через defer), Wait() блокирует, пока счётчик не достигнет 0.

Подробнее →
3 Чем atomic.Int64 (Go 1.19+) лучше прямого использования atomic.AddInt64? 🟢 Лёгкий
Ответ: B) Типобезопасный API с методами Add, Load, Store, Swap - без передачи указателя и проблем с выравниванием на 32-bit

atomic.Int64 инкапсулирует значение и предоставляет методы (Add, Load, Store, CompareAndSwap). Не нужно помнить про & и выравнивание.

Подробнее →
4 Что делает sync.Once? 🟡 Средний
Ответ: B) Гарантирует однократное выполнение функции

once.Do(f) выполняет функцию f только один раз, даже при вызовах из нескольких горутин. Все остальные вызовы Do блокируются, пока первый не завершится. Используется для ленивой инициализации.

Подробнее →
5 Чем sync.RWMutex отличается от sync.Mutex? 🟡 Средний
Ответ: B) Позволяет нескольким читателям одновременно

RWMutex разделяет блокировки на чтение (RLock/RUnlock) и запись (Lock/Unlock). Несколько горутин могут одновременно читать, но запись эксклюзивна. Эффективнее Mutex, когда чтений больше записей.

Подробнее →
6 Что делает sync.OnceValue[T](f func() T) (Go 1.21+)? 🟡 Средний
Ответ: A) Возвращает функцию, вызывающую f один раз и кеширующую результат

sync.OnceValue возвращает функцию, которая при первом вызове выполнит f и запомнит результат. Все последующие вызовы возвращают кешированное значение без повторного вычисления. Потокобезопасна. sync.OnceValues - для функций с двумя результатами.

Подробнее →
7 Какая ошибка: var wg sync.WaitGroup; for i := 0; i < 5; i++ { go func() { wg.Add(1); work(); wg.Done() }() }; wg.Wait()? 🟡 Средний
Ответ: B) wg.Add(1) должен вызываться ДО запуска горутины

wg.Add(1) внутри горутины - гонка: wg.Wait() может завершиться до того, как горутины вызовут Add. Правильно: wg.Add(1) перед go func(). Или wg.Add(5) перед циклом. Без этого Wait() может вернуть 0 и программа завершится раньше горутин.

Подробнее →
8 Для чего нужен sync.Cond? 🟡 Средний
Ответ: B) Для ожидания условия: Wait атомарно отпускает мьютекс и засыпает, Signal будит одну горутину, Broadcast - все

sync.Cond позволяет горутинам ждать наступления условия. Wait() отпускает мьютекс и блокируется. Signal() будит одну ждущую горутину, Broadcast() - все.

Подробнее →
9 Почему sync.Cond.Wait() нужно вызывать в цикле for, а не под if? 🟡 Средний
Ответ: A) Wait может вернуться без Signal (spurious wakeup), поэтому после пробуждения нужно перепроверить условие

Возможны ложные пробуждения (spurious wakeups). Паттерн: for !condition() { cond.Wait() }. После пробуждения проверяем условие заново.

Подробнее →
10 Можно ли копировать sync.Mutex? 🔴 Сложный
Ответ: B) Нет, это приведёт к багам

Копирование мьютекса копирует его внутреннее состояние (заблокирован/нет). Копия может быть в заблокированном состоянии, что приведёт к deadlock. go vet обнаруживает копирование мьютексов.

Подробнее →
11 Что будет, если функция в sync.Once.Do(f) вызовет panic? 🔴 Сложный
Ответ: B) Do считается выполненным, f больше не вызовется

sync.Once гарантирует однократный вызов. Даже если f паникует, Once считается выполненным. Повторные Do() ничего не сделают. Если инициализация обязательна - обрабатывайте panic внутри f или используйте другой подход.

Подробнее →
12 Что произойдёт при вызове wg.Done() больше раз, чем wg.Add()? 🔴 Сложный
Ответ: B) panic: negative WaitGroup counter

Done() уменьшает внутренний счётчик на 1. Если счётчик уходит ниже нуля - panic. Всегда вызывайте Add(n) до запуска горутин и Done() ровно n раз. Используйте defer wg.Done() в начале горутины для гарантии.

Подробнее →
13 Можно ли разблокировать sync.Mutex из другой горутины (не из той, где был Lock)? 🔴 Сложный
Ответ: B) Да, мьютекс не привязан к горутине

sync.Mutex не привязан к горутине (не reentrant). Любая горутина может вызвать Unlock(). Это значит, что повторный Lock() в той же горутине вызовет deadlock - мьютекс не рекурсивный. Отличие от мьютексов в Java/C#.

Подробнее →
14 Когда sync.Map эффективнее обычного map с sync.RWMutex? 🔴 Сложный
Ответ: C) При редких записях и частых чтениях со стабильным набором ключей

sync.Map оптимизирован для: 1) ключи стабильны (много чтений, мало записей); 2) разные горутины работают с разными ключами. Для частых записей обычный map + sync.RWMutex эффективнее. sync.Map не типизирован (работает с any), что является его минусом.

Подробнее →
🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.