liveBook · Manning

Barrier

As explained in Learn Concurrent Programming with Go

A barrier is a synchronization mechanism that suspends participating executions until all of them reach the same execution point, after which they resume and may participate again.

A barrier synchronizes a fixed group of concurrent executions at a shared point. Each participant calls Wait() after reaching that point and remains suspended until every participant has arrived. The barrier then releases the group together, letting the next phase begin. Unlike a waitgroup, which waits for tasks to finish, a barrier coordinates executions before or between pieces of work. section 6.2 section 6.2.1

Barriers fit repeated, phase-based work. Goroutines can compute independently, wait for input to become ready, compute again, then wait while another execution collects results. A reusable barrier is a cyclic barrier: after releasing one group, it can synchronize the same participants at a later execution point. section 6.2.1

A condition-variable barrier needs three pieces of shared state:

  • A barrier size: the total number of participating goroutines expected at each Wait() point. section 6.2.2
  • A wait counter: incremented as each goroutine arrives, tracking how many are currently waiting. section 6.2.2
  • A condition variable and mutex: the mutex protects the counter; the condition variable suspends early arrivals and broadcasts when the group is complete. section 6.2.2

Wait() combines the roles that Done() and Wait() play for a waitgroup into one atomic operation. A goroutine locks the barrier state and increments the counter. If it is not the last participant, it waits on the condition variable. If its arrival brings the count to the barrier size, it resets the counter to zero and broadcasts to unblock the suspended goroutines. Resetting the count makes the barrier reusable for another cycle. section 6.2.1 section 6.2.2

Fast and slow goroutines meeting repeatedly

Two goroutines share a barrier of size two. Red works for four seconds while Blue works for ten. Red reaches Wait() first and pauses; when Blue reaches Wait(), both resume at nearly the same time. On the next cycle, Red again waits for Blue. The output makes the key behavior visible: a barrier does not equalize work duration, but it prevents either participant from passing the synchronization point alone. section 6.2.2

Figure 6.10 Waiting when not all goroutines are at barrier, and broadcasting and resuming barriers when all goroutines are at the barrier

Compare the early-arrival path, which waits, with the final-arrival path, which resets the count and broadcasts to the group. section 6.2.2

All intended participants must reach every barrier cycle. The configured size is therefore part of the protocol: it must match the goroutines that share the barrier, including a coordinating main goroutine when it also waits. A barrier is useful when work must proceed in ordered stages, rather than merely when a caller needs notification that tasks have ended. section 6.2.2 section 6.2.3

Concurrent matrix multiplication in phases

For a 3 × 3 result matrix, three row goroutines and main use a barrier of size four. Main generates the input matrices while row goroutines wait. Its first Wait() releases the row goroutines to calculate their assigned rows. Each row then waits again; after all rows finish, main is released to print the result and load the next matrices. Reusing both the goroutines and barrier supports repeated multiplications. section 6.2.3

An alternative is to create a fresh set of row goroutines for each matrix instead of reusing workers through a barrier. That design still needs a way to notify main when all row calculations are complete. Barriers are consequently most natural when the same group repeatedly crosses the same coordination boundaries. section 6.3

How Learn Concurrent Programming with Go covers it

How deep it goes
Builds a reusable Go barrier with a condition variable, mutex, counter, and broadcast-based Wait() operation.
Examples
Demonstrates fast and slow goroutines rendezvousing and row goroutines performing repeated matrix multiplication phases.
What it assumes
Introduces barriers through goroutines and Wait() calls while assuming familiarity with concurrent executions and waitgroups.
What you can do after
Build it from scratch as a reusable Go barrier and apply it to coordinate repeated worker phases.
How it connects
Contrasts barriers with waitgroups and connects them to condition variables, mutexes, goroutines, and matrix multiplication.

Also explained in

Compare how 3 books explain barrier →

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.