liveBook · Manning

Wait

As explained in Learn Concurrent Programming with Go

Wait is a condition-variable operation that suspends an execution until the condition variable is signaled or broadcast while coordinating the wait with an associated mutex.

`Wait` suspends a goroutine until shared state may have changed. It is a condition-variable operation, used with an associated mutex: while holding the mutex, test the condition; if it is false, call `Wait`. The call atomically releases the mutex and blocks the goroutine, so another goroutine can update the state. When awakened by `Signal` or `Broadcast`, `Wait` reacquires the mutex before returning. section 5.1.1 section 5.4

Keep the condition test in a `for` loop. A wake-up means the goroutine may recheck shared state, not that its required state is guaranteed. If the condition remains false, it waits again; if true, it continues while still holding the mutex. section 5.1.1 section 6.1.4

Waiting for funds

A spending goroutine locks `cond.L` and waits while `money < 50`. `Wait` lets the earning goroutine acquire that mutex, add funds, call `Signal`, and unlock. The spender wakes, reacquires the mutex, rechecks the balance, and subtracts only when enough money exists. section 5.1.1

`Signal` wakes one waiting goroutine, chosen arbitrarily when several are waiting. `Broadcast` wakes every goroutine currently waiting on the condition variable. Use broadcast when one state change can satisfy a group of waiters, such as all players being connected. section 5.1.3 section 5.4

A signal sent when no goroutine is waiting is missed; it is not saved for a later `Wait`. Coordinate signaling with the same mutex: a waiter releases that mutex only as it enters `Wait`, and a signaler locks it while signaling. Otherwise a program can wait forever and deadlock. section 5.1.2 section 5.4

Listing 5.5 Spendy waiting for more funds to be available
func spendy(money *int, cond *sync.Cond) {
    for i := 0; i < 200000; i++ {
        cond.L.Lock()               #1
        for *money < 50 {           #2
            cond.Wait()             #2
        }
        *money -= 50                #3
        if *money < 0 {
            fmt.Println("Money is negative!")
            os.Exit(1)
        }
        cond.L.Unlock() 
    }
    fmt.Println("Spendy Done")
}
#1 Uses the mutex on the condition variable
#2 Waits while we don’t have enough money, releasing mutex and suspending execution
#3 Returning from Wait(), reacquires the mutex and subtracts money once there is enough money

This listing shows the core `for`-and-`Wait` pattern: lock, test the balance, wait while insufficient, then proceed after the mutex is reacquired. section 5.1.1

A waitgroup built from a condition variable

A custom waitgroup can lock around `groupSize`, then call `Wait` while the size is above zero. Each `Done` decrements the size; the final `Done` broadcasts so every goroutine waiting for completion can resume. section 6.1.4

How Learn Concurrent Programming with Go covers it

How deep it goes
Explains atomic unlock-and-suspend behavior, wake-up reacquisition, looped checks, missed signals, and condition-variable waitgroup construction.
Examples
Uses a bank balance, a multiplayer-game lobby, missed completion signals, and a custom waitgroup.
What it assumes
Introduces condition-variable waiting alongside mutex-protected shared state without assuming prior condition-variable terminology.
What you can do after
Apply it via Go's sync.Cond to suspend goroutines safely until shared-state conditions change.
How it connects
Connects condition variables with mutexes, Signal, Broadcast, semaphores, waitgroups, and readers-writer locks.

Also explained in

Compare how 4 books explain wait →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Concurrent Programming with Go. The section links point to the parts of the book it draws on.