sync.Cond.Wait() может вернуться без фактического вызова Signal/Broadcast (spurious wakeup). Кроме того, между Signal и пробуждением горутины другая горутина может изменить состояние.
// Неправильно - if:
mu.Lock()
if !ready {
cond.Wait() // проснулись, но ready мог снова стать false
}
process() // может сломаться!
mu.Unlock()
// Правильно - for:
mu.Lock()
for !ready {
cond.Wait() // после пробуждения проверяем условие заново
}
process() // гарантированно ready == true
mu.Unlock()
Это стандартный паттерн для condition variables во всех языках (C++, Java, Go). Цикл гарантирует, что горутина продолжит работу только когда условие действительно выполнено.