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. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, and your progress syncs across the web and the CoddyKit app. The C++ Academy course includes 4 lessons in total.
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.
Learn C++ with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 51
- Lessons
- 203
Frequently Asked Questions
Is the “Condition Variables and Worker Patterns” lesson free?
Yes — any 3 lessons of the C++ Academy learning path, including “Condition Variables and Worker Patterns”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The C++ Academy course includes 4 lessons in total.
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, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
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