I have a queue of worker thread IDs in C++, and a coordinator thread wakes each thread in order. The woken thread then interacts with the coordinator thread to perform some work. Once done, the coordinator wakes the next thread.
I am considering two approaches to implement this:
- Separate Condition Variables: Each worker thread has its own
std::condition_variable, stored in a queue along with its thread ID. The coordinator signals the respective condition variable to wake up a specific thread. - Single Condition Variable: All worker threads wait on a shared
std::condition_variable, using a predicate to check if their ID matches the one chosen by the coordinator.
Approach 2: Using a Single Condition Variable
Coordinator Thread:
while (true) {
{
std::lock_guard<std::mutex> lock(mtx);
id_chosen_by_coordinator = workerThreads.front();
workerThreads.pop();
}
cv.notify_all(); // Wake up all worker threads, but only one will proceed
...
}
Worker Thread:
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []() { return myid == id_chosen_by_coordinator; });
...
Which of these approaches is preferable in terms of efficiency and correctness? Are there potential pitfalls with the single condition variable approach, such as unnecessary wake-ups or race conditions?
cv.wait. If the thread is awakened "spuriously," then your condition,myid==id_chosen_by_coordinatorwill be false, and thewaitwill go back to sleep and wait again for the real notification. The way you wrote it, thewaitwill not return untilmyid==id_chosen_by_coordinatoractually is true.