# Thread Synchronization Primitives in absl::synchronization: A Complete Guide

> Explore absl::synchronization primitives like Mutex, CondVar, Notification, and Barrier. Discover deadlock detection and reader-writer locks for high-performance C++.

- Repository: [Abseil/abseil-cpp](https://github.com/abseil/abseil-cpp)
- Tags: deep-dive
- Published: 2026-07-12

---

**The `absl::synchronization` library provides seven core thread synchronization primitives—`Mutex`, `CondVar`, `Notification`, `Barrier`, `BlockingCounter`, `ThreadPool`, and `Condition`—that offer deadlock detection, reader-writer locks, and cross-platform atomic operations for high-performance C++ applications.**

The abseil/abseil-cpp repository delivers a robust concurrency toolkit through its `absl/synchronization` module. These header-only thread synchronization primitives are designed for production-grade C++ applications requiring fine-grained control over thread coordination, from basic mutual exclusion to complex barrier synchronization.

## Core Synchronization Primitives

The public API exposes six primary synchronization building blocks, all declared in header-only files under `absl/synchronization/`.

### absl::Mutex

`absl::Mutex` is a non-reentrant mutual-exclusion lock declared in [`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h). Unlike standard mutexes, it provides a starvation-free reader-writer mode, deadlock detection, and invariant debugging capabilities.

Key methods include:
- `lock()` and `unlock()` for exclusive access
- `lock_shared()` and `unlock_shared()` for concurrent read access
- `try_lock()` and `try_lock_shared()` for non-blocking attempts
- Condition-based helpers: `LockWhen()`, `Await()`, and `AwaitWithTimeout()`

The library provides RAII wrappers `absl::MutexLock` and `absl::ReaderMutexLock` to ensure exception-safe lock management.

```cpp
#include "absl/synchronization/mutex.h"

absl::Mutex mu;
int shared_data = 0;

void Increment() {
  absl::MutexLock lock(mu);        // acquires mu exclusively
  ++shared_data;                   // critical section
}  // mu is automatically released here

```

For reader-writer scenarios, use `absl::ReaderMutexLock` to acquire shared locks:

```cpp
#include "absl/synchronization/mutex.h"

absl::Mutex mu;
int read_only = 0;

void Reader() {
  absl::ReaderMutexLock lock(mu);  // acquires a shared lock
  // safe to read `read_only` concurrently with other readers
}

void Writer() {
  absl::MutexLock lock(mu);        // exclusive lock
  ++read_only;                     // exclusive modification
}

```

### absl::CondVar

`absl::CondVar` implements the classic condition variable pattern and is defined alongside `Mutex` in [`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h). It enables threads to wait for arbitrary predicates while atomically releasing the associated mutex.

Key API:
- `Wait(Mutex*)` - Atomically releases the mutex and blocks until signaled
- `WaitWithTimeout()` - Blocks with a time limit
- `Signal()` - Wakes one waiting thread
- `SignalAll()` - Wakes all waiting threads

```cpp
#include "absl/synchronization/mutex.h"
#include "absl/synchronization/condvar.h"

absl::Mutex mu;
absl::CondVar cv;
bool ready = false;

void Waiter() {
  absl::MutexLock lock(mu);
  while (!ready) {
    cv.Wait(&mu);                 // atomically releases mu and blocks
  }
  // `ready` is true here
}

void Signaler() {
  {
    absl::MutexLock lock(mu);
    ready = true;
  }
  cv.Signal();                     // wakes one waiter
}

```

### absl::Notification

`absl::Notification` provides a lightweight one-shot event mechanism for signaling completion between threads. Declared in [`absl/synchronization/notification.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/notification.h), it supports the common pattern where one thread must wait for another to finish an operation.

Methods:
- `Notify()` - Signals the event (idempotent after first call)
- `WaitForNotification()` - Blocks until notified
- `HasBeenNotified()` - Non-blocking status check

```cpp
#include "absl/synchronization/notification.h"

absl::Notification done;

void Worker() {
  // … perform work …
  done.Notify();                  // signal completion (only once)
}

void Waiter() {
  done.WaitForNotification();     // blocks until `Notify()` is called
}

```

### absl::Barrier

`absl::Barrier`, defined in [`absl/synchronization/barrier.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/barrier.h), creates a reusable synchronization point for a fixed number of threads. All participating threads block until the count reaches zero, then immediately reset for the next cycle.

Methods:
- `Block()` - Wait for all participants to arrive
- `BlockWhen(absl::Condition const&)` - Conditional barrier wait

```cpp
#include "absl/synchronization/barrier.h"

constexpr int kNumThreads = 4;
absl::Barrier barrier(kNumThreads);

void ThreadFunc() {
  // ... work before barrier ...
  barrier.Block();                // all kNumThreads block here
  // ... work after all threads have arrived ...
}

```

### absl::BlockingCounter

`absl::BlockingCounter` implements a thread-safe countdown latch in [`absl/synchronization/blocking_counter.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/blocking_counter.h). It blocks callers until the internal counter reaches zero, making it ideal for "wait-for-all" completion patterns.

Methods:
- `DecrementCount()` - Decreases the counter
- `Wait()` - Blocks until counter reaches zero

This primitive differs from `Barrier` in that it is not reusable—once the count reaches zero, the object cannot be reset.

## Advanced Utilities

### absl::ThreadPool

While technically internal, `absl::synchronization_internal::ThreadPool` in [`absl/synchronization/internal/thread_pool.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/internal/thread_pool.h) provides an autoscaling thread pool for task scheduling. It relies on the lower-level synchronization primitives for thread coordination.

Key methods:
- `Schedule(std::function<void()> task)` - Enqueue work
- `NumThreads()` - Query current thread count

```cpp
#include "absl/synchronization/internal/thread_pool.h"

absl::synchronization_internal::ThreadPool pool(/*num_threads=*/4);

void Foo() {
  pool.Schedule([]{
    // task body executed by one of the pool's threads
  });
}

```

### absl::Condition

`absl::Condition` is a helper class defined in [`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h) that encapsulates predicate functions for use with `Mutex` waiting operations. It supports various constructors for free functions, member functions, lambdas, and boolean pointers, enabling type-safe condition checking with `LockWhen()` and `Await()`.

## Implementation Architecture

The high-level primitives in abseil/abseil-cpp build upon a unified internal foundation. Both `Mutex` and `CondVar` utilize `absl::synchronization_internal::PerThreadSem`, a low-level counting semaphore defined in [`absl/synchronization/internal/per_thread_sem.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/internal/per_thread_sem.h).

Platform-specific implementations reside in the internal directory:
- [`absl/synchronization/internal/futex_waiter.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/internal/futex_waiter.h) - Linux futex-based waiting
- [`absl/synchronization/internal/pthread_waiter.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/internal/pthread_waiter.h) - POSIX condition variable implementation
- [`absl/synchronization/internal/win32_waiter.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/internal/win32_waiter.h) - Windows Vista condition variables

These internal components are not part of the public API but demonstrate how the library abstracts OS-specific primitives while maintaining consistent semantics across platforms.

## Summary

- **`absl::Mutex`** provides exclusive and shared locking with deadlock detection in [`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h)
- **`absl::CondVar`** enables condition-based waiting using `Wait()` and `Signal()` APIs
- **`absl::Notification`** offers one-shot signaling via `Notify()` and `WaitForNotification()`
- **`absl::Barrier`** creates reusable synchronization points for N threads with `Block()`
- **`absl::BlockingCounter`** implements countdown latches for "wait-for-all" patterns
- **`absl::Condition`** encapsulates predicates for type-safe mutex waiting
- All primitives are header-only and built on `PerThreadSem` internal abstractions

## Frequently Asked Questions

### How does absl::Mutex detect deadlocks?

According to the abseil/abseil-cpp source code, `absl::Mutex` implements lock-ordering checks and invariant debugging that can detect potential deadlocks during lock acquisition. These debugging features are available in the implementation found in [`absl/synchronization/mutex.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/mutex.h), allowing developers to identify circular dependencies in lock acquisition sequences.

### What is the difference between absl::Barrier and absl::BlockingCounter?

While both coordinate multiple threads, `absl::Barrier`—defined in [`absl/synchronization/barrier.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/barrier.h)—is a reusable synchronization primitive that blocks threads until a predefined count arrives via `Block()`, whereas `absl::BlockingCounter`—defined in [`absl/synchronization/blocking_counter.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/blocking_counter.h)—is a one-shot countdown that blocks until its internal count reaches zero via `DecrementCount()` calls.

### Can absl::Notification be used multiple times?

No, `absl::Notification` is a one-shot event as implemented in [`absl/synchronization/notification.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/notification.h). Once `Notify()` is called, the notification remains signaled indefinitely, and `HasBeenNotified()` will always return true. For repeated signaling patterns, use `absl::CondVar` instead.

### What underlying primitive powers absl::Mutex and absl::CondVar?

Both primitives rely on `absl::synchronization_internal::PerThreadSem`, a low-level counting semaphore defined in [`absl/synchronization/internal/per_thread_sem.h`](https://github.com/abseil/abseil-cpp/blob/main/absl/synchronization/internal/per_thread_sem.h). This internal component manages per-thread wait queues and scheduling across platforms, with platform-specific implementations in the `internal/` directory abstracting futex, pthread, and Win32 APIs.