10.1 std::thread Basics
A thread is an independent path of execution that can run concurrently with others inside the same program, all sharing the same address space in memory.
The <thread> header lets you launch a function on a new thread that runs alongside main(), which is indispensable for tasks like background computation, networking, or physics simulation while the user interface stays responsive.
#include <iostream>
#include <thread>
using namespace std;
void task() {
cout << "running in thread\n";
}
int main() {
thread t(task);
t.join(); // wait for the background thread to finish before exiting main
return 0;
}
10.2 Race Conditions & Mutex
Because threads share memory, two threads modifying the same variable at the same time can interleave unpredictably and corrupt the result — this is called a race condition.
A mutex (mutual exclusion lock) ensures that only one thread can access a shared resource at any given time, forcing every other thread to wait its turn before proceeding.
#include <thread>
#include <mutex>
using namespace std;
mutex mtx;
int counter = 0;
void increment() {
mtx.lock();
counter++;
mtx.unlock();
}
Forgetting to unlock a mutex — especially if an exception is thrown between lock() and unlock() — permanently freezes (deadlocks) every other thread waiting on it. Prefer std::lock_guard, covered next, which unlocks automatically via RAII.
10.3 Thread Synchronization
Beyond raw mutexes, C++ provides higher-level synchronization primitives:
std::lock_guard: Implements RAII (Resource Acquisition Is Initialization) to automatically unlock a mutex the instant it goes out of scope — even if an exception occurs in between.std::condition_variable: Lets a thread sleep efficiently until another thread signals (notifies) that some condition or work item has become available.
#include <mutex>
using namespace std;
mutex mtx;
int counter = 0;
void safeIncrement() {
lock_guard<mutex> lock(mtx); // automatically unlocked at end of scope!
counter++;
}