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.
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; }