Concurrency and the memory model in C++
You write concurrent C++ with std::thread, locks, futures, atomics and parallel algorithms, and find races with ThreadSanitizer and fix them according to the memory model.
Level 401 · 19 lessons · 15 practice labs
Lessons
Threads
- std::thread and std::jthread
- mutex, lock_guard and scoped_lock
- condition_variable and spurious wake-ups
- Read-heavy data with shared_mutex
- Cooperative cancellation with stop_token
- Short task: a thread-safe cache
Tasks and results
- future, promise and async
- packaged_task and a work queue
- Writing a thread pool
- Parallel algorithms: execution policies
- latch, barrier and counting_semaphore
- Short task: a parallel file search
The memory model
- std::atomic and memory orders
- Happens-before and data races
- A lock-free single-producer single-consumer queue
- False sharing and cache lines
- Proving races with ThreadSanitizer
- Short task: find and fix three races
Capstone
- Capstone: a multi-stage processing pipeline with back-pressure
Practice labs
- Splitting a sum across jthreads: Compute the sum of a large vector in parts with four std::jthread objects and show the result equals the single-threaded version.
- Deadlock-free transfer between two accounts: Remove the deadlock in Yelkovan Bankası's mutual transfer code with std::scoped_lock and show by test that the total balance is preserved.
- Making a read-heavy cache thread-safe: Open a cache slowed by a single mutex to readers with shared_mutex and prove no race with TSan and the speed-up with measurements.
- Waiting on a condition variable with a predicate: Fix a consumer that reads from an empty queue on a spurious wake-up by waiting with a predicate.
- Stopping a worker with stop_token: Make a worker running an endless loop stoppable at once, even while sleeping, with stop_token and condition_variable_any.
- Writing a bounded queue that can be closed: Write a bounded queue that blocks producers when full and consumers when empty, whose close call wakes every waiter without losing remaining items.
- Running two queries concurrently with std::async: Run two slow queries that execute in sequence concurrently with std::async and future and test that an exception reaches the caller.
- Building a work queue with packaged_task: Write a single-worker queue with packaged_task that returns a future for each submitted job and verify jobs run in submission order.
- Repairing a thread pool that drops jobs: Repair a pool that drops some jobs and occasionally hangs in its destructor so it finishes pending work and joins every worker, passing a test repeated a thousand times.
- Starting workers together with a latch: Wait for eight workers to be ready with std::latch, release them together and collect their completion with a second latch.
- Limiting concurrent downloads with a semaphore: Ensure at most three fake downloads run at once with counting_semaphore and test that the limit holds and a permit is returned on exception.
- Parallel search in a file tree: Parallelise a tool that searches text in a directory tree with a work queue and workers so results come out unique and ordered and the speed-up is measured.
- Making a request counter atomic: Replace a plain int counter incremented by many threads with std::atomic and show the TSan warning disappears.
- Removing false sharing with alignment: Show by measurement that adjacent per-thread counters share a cache line, separate them with alignment and report the speed-up.
- A lock-free single-producer single-consumer queue: Write a lock-free queue over a ring buffer with correct memory orders and show no loss or duplication over a million items and a clean TSan run.
About this course
You write concurrent C++ with std::thread, locks, futures, atomics and parallel algorithms, and find races with ThreadSanitizer and fix them according to the memory model.
What you will learn
- Threads
- Tasks and results
- The memory model
- Capstone
Prerequisites
You should have practised the topics of the same path up to level 301.
Lab environment
Lessons run in your own Kali Linux terminal that opens in the browser. Nothing to install; the lab starts clean in every lesson.
Frequently asked questions
- Is this course right for my level?
- The course is at level 401; it assumes you know the topics of the lower-level courses.
- Is there anything to install?
- No. Every lesson runs in your own lab environment that opens in the browser.
- How do lessons work?
- Each lesson has 8 to 10 steps and a short quiz. Early steps show the command to type, later steps give less help; if two attempts fail, the solution opens.
- Can I try it for free?
- Yes. The first three lessons of every course are free.