Skip to content

Chapter 30 of 31

Multithreading Basics

Start threads and coordinate shared work with mutexes, locks, atomics, and async tasks.

44 minutes 10 quick checksBy Subha Prasad
Lesson 30 of 31Course navigation

Lesson content

Read, practise, then check your understanding

std::thread starts a thread of execution. A joinable thread must be joined or detached before its destructor, otherwise the program terminates. std::jthread joins automatically and supports cooperative stopping.

#include <mutex>
#include <thread>

int total{};
std::mutex totalMutex;

void add(int value) {
    std::scoped_lock lock{totalMutex};
    total += value;
}

int main() {
    std::jthread first{add, 3};
    std::jthread second{add, 4};
}

A data race occurs when threads access the same memory concurrently, at least one access writes, and no synchronization orders them. It is undefined behavior. std::mutex plus std::lock_guard, std::unique_lock, or std::scoped_lock protects invariants. Keep critical sections small and establish a consistent lock order to prevent deadlock.

Communication choices

Atomics safely coordinate simple independent values, but correct memory ordering is subtle; use default sequential consistency until measurement and proof justify weaker ordering. Condition variables let threads sleep until a predicate may be true and must be checked in a loop because wakeups can be spurious.

std::async and futures communicate a result or exception. Exceptions do not automatically cross thread boundaries; capture them through futures or std::exception_ptr. Prefer immutable data, ownership transfer, message passing, and task-level concurrency over widespread shared mutable state. Test with stress, sanitizers where available, and explicit shutdown behavior.

Knowledge check

Answer every question correctly to complete this chapter.

Which header declares std::thread?
What must happen to a joinable std::thread before destruction?
What protects shared state with mutual exclusion?
Why use std::lock_guard?
What is a data race in C++?
Which facility provides atomic operations?
What does a condition_variable support?
Why should condition-variable waits use a predicate?
What does std::jthread add in C++20?
What is the safest default for shared mutable data?

0 of 10 checks passed

Your progress is saved on this device.