C++ 11 - <atomic> Header

Last Updated : 7 Jul, 2026

The <atomic> header, introduced in C++11, provides atomic types and operations for safely accessing shared data in multithreaded programs. It helps prevent data races by ensuring that operations on shared variables are performed atomically.

  • Provides lock-free synchronization for many primitive data types.
  • Enables safe communication between multiple threads without explicit mutexes.
C++
#include <atomic>
#include <iostream>

using namespace std;

int main()
{
    atomic<int> counter(0);

    counter++;

    cout << counter;

    return 0;
}

Output
1

Explanation: The variable counter is declared as an atomic integer. Incrementing it is performed atomically, making it safe for concurrent access by multiple threads.

Syntax

std::atomic<data_type> variable_name;

Parameters

  • data_type: Primitive type such as int, bool, char, etc.
  • variable_name: Name of the atomic variable.

Common Atomic Operations

The <atomic> header provides several operations for reading, modifying, and synchronizing atomic variables.

FunctionDescription
load()Reads the current value of the atomic variable.
store()Stores a new value into the atomic variable.
exchange()Replaces the current value and returns the previous value.
fetch_add()Atomically adds a value and returns the old value.
fetch_sub()Atomically subtracts a value and returns the old value.
fetch_and()Performs an atomic bitwise AND operation.
fetch_or()Performs an atomic bitwise OR operation.
fetch_xor()Performs an atomic bitwise XOR operation.
wait()Blocks until the atomic value changes. (C++20)
notify_one()Wakes one waiting thread. (C++20)
notify_all()Wakes all waiting threads. (C++20)

Note: wait(), notify_one(), and notify_all() were introduced in C++20, not C++11.

Example of atomic counter

C++
#include <atomic>
#include <iostream>
#include <thread>
using namespace std;

atomic<int> counter(0); // Atomic integer

void increment_counter(int id)
{
    for (int i = 0; i < 100000; ++i) {
        // Increment counter atomically
        counter.fetch_add(1);
    }
}

int main()
{
    thread t1(increment_counter, 1);
    thread t2(increment_counter, 2);

    t1.join();
    t2.join();

    cout << "Counter: " << counter.load() << std::endl;

    return 0;
}

Output
Counter: 200000

Explanation

  • Two threads increment the same atomic counter.
  • fetch_add() performs each increment atomically.
  • The final result is correct because no data races occur.

std::atomic_flag

std::atomic_flag is the simplest atomic type provided by the <atomic> header. It represents a lock-free boolean flag and is commonly used to implement lightweight synchronization mechanisms such as spinlocks. It provides the following operations:

FunctionDescription
test()Reads the current flag value. (C++20)
test_and_set()Sets the flag and returns its previous value.
clear()Resets the flag.

Example: Using std::atomic_flag

C++14
#include <atomic>
#include <iostream>
#include <thread>

using namespace std;

atomic_flag flag = ATOMIC_FLAG_INIT;

void work(int id)
{
    while (flag.test_and_set(memory_order_acquire))
        ;

    cout << "Thread " << id << " is running\n";

    flag.clear(memory_order_release);
}

int main()
{
    thread t1(work, 1);
    thread t2(work, 2);

    t1.join();
    t2.join();

    return 0;
}

Output
Thread 1 is running
Thread 2 is running

Explanation

  • test_and_set() atomically acquires the flag.
  • Only one thread enters the critical section at a time.
  • clear() releases the flag so another thread can proceed.

Advantages of <atomic>

The <atomic> header offers several benefits:

  • Prevents data races in multithreaded programs.
  • Supports efficient lock-free programming on many platforms.
  • Improves performance for lightweight shared data access.

Limitations of <atomic>

Despite its advantages, <atomic> has some limitations:

  • Works primarily with individual variables, not complex operations.
  • Incorrect memory ordering can still introduce synchronization bugs.
  • Complex shared resources often still require mutexes.
Comment