C++ Multithreading: jthread, mutex, atomic, Memory Model & Lock-Free Programming (C++20)

C++ Multithreading: jthread, mutex, atomic, Memory Model & Lock-Free Programming (C++20)
Table of Contents
- The C++ Concurrency Landscape
- std::jthread: RAII Thread with Stop Support (C++20)
- std::stop_token: Cooperative Cancellation
- Mutex Types and When to Use Each
- scoped_lock: Multi-Mutex Deadlock Prevention
- condition_variable: Producer-Consumer Pattern
- The C++ Memory Model: happens-before and memory_order
- std::atomic: Lock-Free Operations
- Atomic Fences: standalone memory barriers
- std::latch, std::barrier & std::semaphore (C++20)
- Thread Pool Design with jthread and queue
- Frequently Asked Questions
- Key Takeaway
The C++ Concurrency Landscape
std::jthread: RAII Thread with Stop Support (C++20)
std::thread (C++11) crashes if it goes out of scope without being joined or detached. std::jthread (C++20) fixes this by auto-joining in its destructor:
Mutex Types and When to Use Each
| Mutex Type | Description | Use When |
|---|---|---|
std::mutex | Basic mutual exclusion | Default choice |
std::recursive_mutex | Same thread can lock multiple times | Recursive functions that need the lock |
std::timed_mutex | Trylock with timeout | Avoid deadlock with deadline |
std::shared_mutex | Multiple readers / one writer | Read-heavy data structures |
scoped_lock: Multi-Mutex Deadlock Prevention
Acquiring multiple mutexes in different orders across threads is a classic deadlock scenario. std::scoped_lock (C++17) acquires all mutexes atomically using a deadlock-avoidance algorithm:
condition_variable: Producer-Consumer Pattern
The C++ Memory Model: happens-before and memory_order
The C++ memory model defines when writes in one thread become visible to reads in another. Without it, the compiler and CPU are free to reorder operations:
Memory orders (ordered from strongest to weakest):
| memory_order | Guarantee | Cost |
|---|---|---|
seq_cst | Total global ordering of all atomic ops | Highest (memory barrier) |
acq_rel | acquire + release on one operation | Medium |
release | All prior writes visible to acquire in other thread | Low |
acquire | Sees all writes released before this load | Low |
relaxed | Only atomicity — no ordering guarantees | Lowest |
std::atomic: Lock-Free Operations
std::latch, std::barrier & std::semaphore (C++20)
Thread Pool Design with jthread and queue
Frequently Asked Questions
When should I use std::async vs std::jthread?
Use std::async for simple parallel computations that return a value — it returns a std::future<T> you can get() later. Use std::jthread for long-running services, event loops, or any thread that runs until explicitly stopped. For structured concurrency (C++26 planned), prefer executors and coroutines over raw threads.
What is a data race and how is it different from a race condition? A data race is when two threads concurrently access the same memory location, at least one write, with no synchronization — this is undefined behavior in C++. A race condition is a logical bug where the program outcome depends on execution order — even with synchronization, wrong locking can produce wrong results. ASan + TSan (ThreadSanitizer) detect data races at runtime.
Is std::atomic always lock-free?
Check with is_lock_free() at runtime, or is_always_lock_free at compile time. Integral types (int, long, ptr) are always lock-free on modern platforms. For types larger than a register (>8 bytes), the implementation uses an internal mutex, defeating the purpose of atomic.
Key Takeaway
C++ concurrency in 2026 means std::jthread + std::stop_token for thread lifecycle, scoped_lock for multi-mutex deadlock prevention, shared_mutex for read-heavy workloads, and std::atomic with correct memory orders for lock-free state. The C++ memory model is not optional — incorrect ordering produces subtle, hardware-specific bugs that are nearly impossible to reproduce in debug builds.
Read next: C++20 Coroutines: Asynchronous Flow Control →
Part of the C++ Mastery Course — 30 modules from modern C++ basics to expert systems engineering.
