← Concepts

阅读中文版本

Atomic Operations

Atomic operations read and modify a value indivisibly, providing lock-free building blocks for counters, flags, and lock-free data structures.

concurrency

Definition

An atomic operation completes as an indivisible unit with respect to other threads, so no observer sees an intermediate state and no update is lost.

Context and scope

It is used for counters, spin flags, reference counts, and the primitives on which larger synchronisation constructs are built.

Common misconceptions

  • atomic operations are always faster than locks
  • an atomic read is enough when updating several related fields

Anti-patterns

  • updating two atomics that must change together without a lock
  • choosing a relaxed memory ordering by default

Related concepts

Related examples

Authoritative source

https://en.cppreference.com/w/cpp/atomic/atomic

Definition

An atomic operation completes as an indivisible unit with respect to other threads, so no observer sees an intermediate state and no update is lost.

It is used for counters, spin flags, reference counts, and the primitives on which larger synchronisation constructs are built. Compared to simpler alternatives, this concept fits best when the trade-off it represents is the one the system actually cares about.

When to use it

A common use case is applying it at the boundary where the cost of getting it wrong is highest, and the scenario usually involves a concrete guarantee the system must uphold. Unlike an ad hoc approach, it makes that guarantee explicit, reviewable, and testable.

How it works

Compare-and-swap loops let a value be updated optimistically and retried on contention, which is efficient at low contention but wasteful when many threads fight over one location.

An operation on a single atomic does not make a group of related updates atomic, so invariants that span several variables still need a lock or a single packed state.

Trade-offs and alternatives

Memory ordering parameters matter: relaxed ordering permits reordering, while acquire and release establish the visibility guarantees a caller may need. The main drawback is the extra complexity it introduces, so the benefit should clearly outweigh that cost before a team adopts it.

Common misconceptions

A persistent misconception is that atomic operations are always faster than locks. Another is that an atomic read is enough when updating several related fields. For example, an engineer who assumes otherwise may design around a guarantee that does not actually exist, which only becomes obvious under load or failure.

Anti-patterns to avoid

Two recurring anti-patterns are to updating two atomics that must change together without a lock and to choosing a relaxed memory ordering by default. Both tend to surface as hard-to-debug production issues rather than obvious test failures. Related concepts include Seqlocks, Lock Fairness and Starvation, Coroutines.