sync.Cond †
В старой части сервиса, которая ещё обслуживала старые пакеты, Миша наткнулся на sync.Cond — механизм ожидания, о котором он только читал. Он разобрал, как тот работал, и убедился: в новом коде команды ему места не было.
Cond — условная переменная поверх мьютекса: горутина засыпает до Signal/Broadcast; в большинстве случаев хватает канала, и Cond нужен редко.
Механизм
var (
mu sync.Mutex
cond = sync.NewCond(&mu)
)
// ожидающий:
mu.Lock()
for !ready {
cond.Wait() // разблокирует мьютекс, спит; при пробуждении — снова захватывает
}
mu.Unlock()
// уведомляющий:
mu.Lock()
ready = true
cond.Broadcast() // или Signal — разбудить одного
mu.Unlock()
Wait требует удерживаемый мьютекс: он временно отдаёт его, спит, а при пробуждении захватывает снова. Signal будит одну горутину, Broadcast — всех. Проверка условия — всегда в цикле: пробуждение не гарантирует, что условие всё ещё верно (ложные пробуждения и гонки).
Почему Cond — редкость
Для «жди, пока условие станет верным» почти всегда хватает канала: закрой его — и все проснулись. Cond нужен, когда условие сложное и его нужно перепроверять под мьютексом — например, ожидание «буфер не пуст и не полон» в классических реализациях очередей. Такие задачи в прикладном коде редки.
Правило выбора
Начни с канала или мьютекса. Cond бери, только когда: условие проверяется под мьютексом, пробуждение должно быть выборочным (Signal, не всем) и перепроверка в цикле — естественная часть логики. Во всех остальных случаях Cond — усложнение без выгоды.
Вы узнаете:
- почему проверка условия в цикле обязательна
- как устроен ограниченный буфер на Cond
Проверьте себя
Что делает cond.Wait() с мьютексом?
Почему условие ожидания проверяют в цикле for, а не в if?
Когда Cond нужен вместо канала?
правильных ответов
Cond — ожидание условия под мьютексом с выборочным пробуждением. Редкий инструмент: чаще хватает канала; условие проверяют в цикле.
10 000 ₽ · 60 минут · онлайн