---
description: C++ Concurrency
alwaysApply: false
---

# C++ Concurrency

The C++ memory model is the law. Every concurrent access must be explicitly synchronized.

## Thread Safety Rules

- Immutable data is thread-safe — share freely via `const` references
- Every mutable shared state needs synchronization — no exceptions
- Hold locks for minimum time — compute outside the critical section
- Never hold two locks simultaneously unless using `std::scoped_lock`
- `std::atomic` for single variables, mutex for compound operations

## std::jthread (C++20)

```cpp
auto worker = std::jthread([](std::stop_token stop) {
    while (!stop.stop_requested()) { /* work */ }
});
// Automatically joins on destruction; request stop via worker.request_stop()
```

## Mutex and Locking

```cpp
// RAII locking — always use lock_guard/scoped_lock
void increment() {
    std::lock_guard lock(mutex_);
    ++count_;
}

// Multiple mutexes — deadlock-free
std::scoped_lock lock(from.mutex_, to.mutex_);

// Read-heavy: std::shared_mutex
std::shared_lock lock(mutex_);  // Multiple readers
std::unique_lock lock(mutex_);  // Exclusive writer
```

## Atomics

```cpp
std::atomic<int> counter{0};
counter.fetch_add(1, std::memory_order_relaxed);

// Release-acquire for producer-consumer
ready.store(true, std::memory_order_release);   // Producer
while (!ready.load(std::memory_order_acquire)) {} // Consumer
```

## Parallel Algorithms (C++17)

```cpp
std::sort(std::execution::par, data.begin(), data.end());
auto total = std::transform_reduce(std::execution::par,
    orders.begin(), orders.end(), 0.0, std::plus<>{},
    [](const Order& o) { return o.total(); });
```

## Anti-Patterns

- **Manual lock/unlock** — use RAII (`lock_guard`), never raw `.lock()/.unlock()`
- **Double-checked locking without atomics** — use `std::call_once` or Meyers singleton
- **`volatile` for synchronization** — `volatile != atomic` in C++; use `std::atomic`
