C++ · Advanced level

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

  1. Replace a mutex-protected counter with std::atomic.
  2. Launch one std::async task per file.
  3. Collect the results with get().
  4. 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

  1. When is std::atomic enough without a mutex?

    Show answer

    For single values updated with atomic operations, such as counters or flags.

  2. 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.