Table of Contents

Atomics

Atomics are operations on shared variables that execute indivisibly even when multiple threads access the variable simultaneously. They replace multi-step operations (load, compute, store) with single hardware instructions, preventing lost updates. C11's <stdatomic.h> and C++11's <atomic> expose portable access to atomic load/store, compare-and-swap, test-and-set, and arithmetic operations.

Every atomic operation carries a memory-order specifier controlling how aggressively the compiler and CPU can reorder surrounding accesses.

Example

This example demonstrates atomic operations and their correctness benefits.

// compile: gcc -std=c11 -pthread -O2 -o atomics atomics.c
// run: ./atomics
// description: atomic operations prevent data races in concurrent code
 
#include <stdio.h>
#include <pthread.h>
#include <stdatomic.h>
 
atomic_int counter = 0;
 
void* increment_atomic(void* arg) {
    for (int i = 0; i < 1000000; i++) {
        atomic_fetch_add(&counter, 1);
    }
    return NULL;
}
 
int main() {
    pthread_t threads[4];
    for (int i = 0; i < 4; i++) {
        pthread_create(&threads[i], NULL, increment_atomic, NULL);
    }
    for (int i = 0; i < 4; i++) {
        pthread_join(threads[i], NULL);
    }
    printf("Counter: %d (expected 4000000)\n", atomic_load(&counter));
    return 0;
}