Barrier Synchronization
A barrier is a synchronization point at which every participant must arrive before any proceeds, used to separate phases of a parallel computation so no phase reads half-written state from the next.
Definition
Barrier synchronization is a coordination primitive where a set of threads or processes all wait at a barrier until every participant has arrived, then all are released together, so that the computation proceeds in phases and no phase begins until the previous phase is fully complete across all workers.
Context and scope
Applied in bulk synchronous parallel processing, phased map-reduce, scientific simulation, and any parallel computation with a clear phase boundary.
Common misconceptions
- A barrier is just a join — a join waits for completion; a barrier is reusable across phases, a join is one-shot
- Barriers eliminate the need for locks — they eliminate locks between phases; within a phase, shared state still needs protection
Anti-patterns
- Using a barrier between phases that have no data dependency, serializing phases that could overlap and reducing parallelism
- Forgetting to reset a reusable barrier, so the second phase releases immediately without waiting
Related concepts
Authoritative source
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CyclicBarrier.html
What it is
Barrier synchronization is a coordination primitive where a set of threads or processes all wait at a barrier until every participant has arrived, then all are released together, so that the computation proceeds in phases and no phase begins until the previous phase is fully complete across all workers. Applied in bulk synchronous parallel processing, phased map-reduce, scientific simulation, and any parallel computation with a clear phase boundary. The central difficulty is that interleaving is nondeterministic: the set of possible executions grows super-exponentially with the number of operations, and testing samples a vanishing fraction.
How it works
Correctness is established by reasoning about happens-before relationships, not by running more tests. Synchronization primitives are chosen for the specific guarantee needed — mutual exclusion, publication, or ordering — and composed only with a documented proof of absence of deadlock. Bounded resources apply backpressure rather than unbounded queuing that hides overload until memory exhausts.
When to apply and pitfalls
Apply whenever multiple flows share mutable state or resources. The dominant pitfall is reasoning sequentially about concurrent code — “this can’t happen because A finishes before B” — when in fact the scheduler can interleave at any instruction boundary. The second is using a coarse lock for simplicity and turning parallelism back into serialization.