Golang / GoLang Concurrency Mastery Interview Questions
What is sync.Cond and when do you use it instead of channels?
sync.Cond is a condition variable — a synchronisation primitive for goroutines to wait for or announce a state change on a shared resource. Use it when: many goroutines wait for a complex shared-state predicate; waking all waiters at once is needed; or channels would add unnecessary data-passing overhead.
// Bounded buffer using sync.Cond type BoundedQueue struct { mu sync.Mutex notFull *sync.Cond notEmpty *sync.Cond items []any capacity int } func NewBoundedQueue(cap int) *BoundedQueue { q := &BoundedQueue{capacity: cap} q.notFull = sync.NewCond(&q.mu) q.notEmpty = sync.NewCond(&q.mu) return q } func (q *BoundedQueue) Put(item any) { q.mu.Lock() defer q.mu.Unlock() for len(q.items) == q.capacity { // LOOP â never if! (spurious wakeups) q.notFull.Wait() // atomically releases lock and sleeps } q.items = append(q.items, item) q.notEmpty.Signal() // wake one waiting consumer } func (q *BoundedQueue) Get() any { q.mu.Lock() defer q.mu.Unlock() for len(q.items) == 0 { q.notEmpty.Wait() } item := q.items[0] q.items = q.items[1:] q.notFull.Signal() return item } // cond.Signal() â wake ONE goroutine (when only one should act) // cond.Broadcast() â wake ALL goroutines (when state change affects all)
Key rule: always check the condition in a for loop, never an if. cond.Wait() can return spuriously (OS wakeup without Signal/Broadcast), so the condition must be re-verified after each wakeup. Wait() atomically releases the associated mutex and sleeps; the mutex is re-acquired before returning.
More Related questions...