liveBook · Manning

WaitGroup

As explained in Learn Concurrent Programming with Go

A waitgroup is a synchronization object that allows execution to wait until a counted set of concurrent operations has completed.

A WaitGroup lets one goroutine wait until a counted set of concurrent tasks finishes. Think of it as a project manager: work is handed to several workers, and execution continues only after every assigned task reports completion. This is useful when a main goroutine splits work across goroutines but must not proceed, print final results, or exit too early. section 6.1 section 6.1.1

Figure 6.1 Typical use of a waitgroup

The counter starts at the number of tasks. Wait blocks the waiting goroutine; each Done lowers the count, and the count reaching zero releases the waiter. section 6.1.1

Go provides sync.WaitGroup with three operations:

  • Add(delta) increases the task count, usually before starting goroutines. section 6.1.1
  • Done() decrements the count when a goroutine finishes its assigned task. section 6.1.1
  • Wait() blocks until the count reaches zero, making completion observable without guessing a sleep duration. section 6.1.1

Waiting for independent work

Create a WaitGroup, call Add(4), start four workers with a reference to it, and call Wait in main. Workers can finish in an unpredictable order, but “All complete” appears only after every worker calls Done. This replaces a fixed sleep used merely to hope that concurrent downloads or processing have finished. section 6.1.1 section 6.1.1

The count need not always be known up front. In a recursive filename search, each directory-search goroutine adds one task before spawning work for a discovered subdirectory, then calls Done when its own directory has been examined. Waiting ends only after the entire directory tree has been explored. section 6.1.3

A fixed-size WaitGroup can be built from a semaphore initialized with 1 minus the task count. Wait acquires a permit and each Done releases one; the waiter resumes once permits become positive. This design requires the size at creation and can resume only one waiter, so it does not provide the flexibility of Go’s bundled type. section 6.1.2 section 6.1.4

A more flexible implementation uses a condition variable and mutex-protected group-size counter. Add changes the count under the mutex, Wait loops while the count is positive, and the final Done decrements to zero and broadcasts so all waiting goroutines can resume. The loop around the condition wait preserves the rule that completion means a zero count. section 6.1.4

A WaitGroup tracks completion, not a shared rendezvous point. Use a barrier when participating goroutines must all stop at the same execution point and then continue together; a WaitGroup instead lets waiting goroutines continue once all tracked work has finished. section 6.0 section 6.4

How Learn Concurrent Programming with Go covers it

How deep it goes
Explains Add, Done, and Wait, then builds fixed and dynamically sized implementations from semaphores and condition variables.
Examples
Uses four delayed workers, concurrent letter-frequency counting, and recursive filename search.
What it assumes
Introduces waitgroups through goroutine task coordination, while later implementations rely on semaphores, condition variables, and mutexes.
What you can do after
Build it from scratch with semaphore or condition-variable primitives, and apply sync.WaitGroup to await concurrent work.
How it connects
Connects waitgroups with goroutines, semaphores, condition variables, mutexes, and barriers.

Also explained in

Compare how 5 books explain WaitGroup →

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.