# Threads, Mutexes and Atomics — C++

Source: https://www.skillbyai.com/en/cpp/a-concurrency

> Write basic concurrent code with jthread, mutexes, lock guards and atomics.

## Doing several things at once safely

Since C++11, the standard library includes concurrency support. **`std::thread`** starts a new thread running a function; it must be **joined** or **detached** before destruction, or the program terminates. **`std::jthread`** (C++20) joins automatically in its destructor and supports cooperative cancellation through a `std::stop_token`, so prefer it. When threads share data and at least one writes, you need **synchronisation**, otherwise you have a **data race**, which is undefined behaviour. **`std::mutex`** with **`std::lock_guard`** or **`std::scoped_lock`** (RAII locks) protects critical sections; `std::scoped_lock` can lock several mutexes without deadlock. **`std::atomic<T>`** provides lock-free operations on simple values such as counters and flags. **`std::condition_variable`** lets threads wait for conditions. **`std::async`** and **`std::future`** run tasks and retrieve results. For parallel algorithms, C++17 added **execution policies** (`std::execution::par`) to many standard algorithms. Keep shared mutable state minimal; passing messages or giving each thread its own data avoids most bugs.

## Counting safely from several threads

Atomic counter, mutex-protected vector and automatically joined threads.

```cpp
#include <atomic>
#include <mutex>
#include <thread>
#include <vector>

int main() {
    std::atomic<long long> hits{0};
    std::vector<int> results;
    std::mutex results_mutex;

    {
        std::vector<std::jthread> workers;
        for (int t = 0; t < 4; ++t) {
            workers.emplace_back([&, t] {
                for (int i = 0; i < 100'000; ++i) {
                    hits.fetch_add(1, std::memory_order_relaxed);   // atomic: no data race
                }
                std::scoped_lock lock(results_mutex);              // RAII lock
                results.push_back(t);
            });
        }
    }   // jthreads join automatically here

    // hits == 400'000 and results holds 4 entries
}
```

## A shared whiteboard with a marker

A mutex is the single marker for a shared whiteboard: only the person holding it may write. An atomic counter is a tally clicker that everyone can press without clashing. Without either, people overwrite each other's work.

**Quiz:** What happens if two threads modify the same int without synchronisation?

- [ ] The result is always correct
- [ ] The compiler adds a lock automatically
- [ ] One thread is blocked automatically
- [x] It is a data race, which is undefined behaviour

*Answer:* It is a data race, which is undefined behaviour. Unsynchronised concurrent writes (or a write with a read) are data races and undefined behaviour.
