Condition Variables and Worker Patterns
Coordinate threads with std::condition_variable and the classic worker pool pattern.
Condition Variables and Worker Patterns is a free C++ Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What is a Condition Variable?
A condition variable lets a thread wait until another thread signals that a condition has changed. Used to coordinate producers and consumers.
std::condition_variable Basics
A condition variable works with a std::mutex and a predicate. The waiting thread releases the lock while waiting and re-acquires it on wake.
#include <condition_variable>
#include <mutex>
#include <queue>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> tasks;
bool done = false;Waiting on a Condition
Use cv.wait(lock, predicate). It atomically unlocks the mutex and sleeps until notified. On wake, it re-locks and checks the predicate; if false, it sleeps again.
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !tasks.empty() || done; });Notifying
The producer thread calls cv.notify_one() or cv.notify_all() after changing the state. The lock should be held during the state change.
{
std::lock_guard<std::mutex> lock(mtx);
tasks.push(42);
}
cv.notify_one();Producer-Consumer Pattern
Classic example: producers push tasks; consumers wait for tasks.
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !tasks.empty() || done; });
if (done && tasks.empty()) break;
int task = tasks.front();
tasks.pop();
lock.unlock();
process(task);
}
}Spurious Wakeups
A thread waiting on a condition variable can wake up without a notify. That is why wait takes a predicate — it re-checks on every wake.
notify_one vs notify_all
Use notify_one when one waiter can make progress. Use notify_all when state changes affect all waiters (e.g., shutdown signal).
Timed Waits
wait_for(lock, duration) and wait_until(lock, time_point) wake either on notify or after a timeout.
if (cv.wait_for(lock, 1s, [] { return ready; })) {
/* condition met */
} else {
/* timed out */
}Worker Pool Skeleton
A common pattern: a fixed set of worker threads pull from a shared queue. Build with mutex + condition_variable + queue + atomic stop flag.
Avoiding Lost Wakeups
Always modify shared state and call notify_* with the mutex held during the state change (release just before notify is fine, but ensure ordering). Otherwise a waiter may miss the notification.
std::counting_semaphore (C++20)
For simple count-based signaling, C++20 added std::counting_semaphore — simpler than condition variables for some patterns.
Beware of Deadlock
Holding multiple locks while waiting on a condition variable can lead to deadlock. Acquire locks in a consistent order, and use std::scoped_lock for multiple mutexes.
Quick Check
Why does cv.wait(lock, predicate) take a predicate even when you just want to wait for a notify?
Recap
A condition variable coordinates threads waiting for a state change. Use wait(lock, predicate) to handle spurious wakeups, modify state under the mutex, and call notify_one or notify_all after.
Frequently asked questions
Is the “Condition Variables and Worker Patterns” lesson free?
Yes — the full text of “Condition Variables and Worker Patterns” is free to read here on the web, and the C++ Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C++ Academy course, upgrade to CoddyKit PRO.
What will I learn in “Condition Variables and Worker Patterns”?
Coordinate threads with std::condition_variable and the classic worker pool pattern. You practise C++ Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C++ Academy?
No prior experience is required. C++ Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Condition Variables and Worker Patterns” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C++ Academy lesson?
Yes. Every C++ Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- std::thread Joining and Detaching
- std::mutex lock_guard and unique_lock
- Condition Variables and Worker Patterns
- std::async and std::future Basics