Advanced level · Module 5: Concurrency in Modern C++ · Lesson 3 of 4
Atomics, Futures and Tasks
Use atomics for simple shared counters and std::async with futures to run tasks that return results.
In this lesson you will
- Use std::atomic for simple shared values
- Run tasks with std::async and collect results with futures
Key concepts
std::atomicstd::asyncstd::futuretask-based parallelism
The lesson
std::atomic<int> supports thread-safe operations such as fetch_add without a mutex. Atomics suit simple counters and flags; anything involving several related values still needs a mutex.
std::async runs a function, possibly on another thread, and returns a std::future. Calling get() waits for the result and rethrows any exception the task threw. Launch with std::launch::async to make sure it runs in parallel.
Task-based design — each task processes its own input and returns a result — avoids most sharing problems. Combine results after all futures complete.
Step by step
- Replace a mutex-protected counter with std::atomic.
- Launch one std::async task per file.
- Collect the results with get().
- Throw from one task and catch the exception at get().
Practice activity
Complete the practical activity: process each sensor file in its own task and combine the results.
Expected result: Parallel and sequential results are identical and an error in one file is reported clearly.
Check your understanding
-
When is std::atomic enough without a mutex?
Show answer
For single values updated with atomic operations, such as counters or flags.
-
What happens to an exception thrown inside a std::async task?
Show answer
It is stored and rethrown when get() is called on the future.
Taught live by an instructor — online or in person. Free course lessons are for self-study and do not lead to a certificate — see registration options.