Reputation: 97
// condition_variable example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id (int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck);
// ...
std::cout << "thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();
}
int main ()
{
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10; ++i)
threads[i] = std::thread(print_id,i);
std::cout << "10 threads ready to race...\n";
go(); // go!
for (auto& th : threads) th.join();
return 0;
}
How does condition_variable work here? It calls "go()" before the threads join, so doesn't that mean no threads are waiting? And it is calling "notify_all()" in "go()", is it doing anything by notifying all?
Upvotes: 0
Views: 98
Reputation: 238401
It calls "go()" before the threads join, so doesn't that mean no threads are waiting?
No, it does not mean that. There may be any number of threads waiting, depending on which threads have had the chance to execute and start waiting before go
does. It is certainly possible - although unlikely if there are multiple hardware threads - that go
notifies before any thread has started waiting but that is not a necessity.
Joining means that the thread which calls the join will wait for the thread that was called on to end, before the calling thread resumes. If go
was called after joining, then the program would never finish because the threads in the array are waiting on the condition variable and the main thread is waiting for the other threads to end before setting the variable.
And it is calling "notify_all()" in "go()", is it doing anything by notifying all?
It notifies all threads that may be waiting on the condition variable. If no thread is waiting, then no thread will react to the notification.
Upvotes: 2
Reputation: 63019
The threads start executing on the line threads[i] = std::thread(print_id,i);
Each thread will acquire the mutex, then release it by waiting on the condition variable. This pauses the execution of that thread.
When go()
is run, it wakes all the threads, and they resume executing. The th.join()
calls are the main method waiting for each worker thread to be finished before the program exits.
Note that only the threads that managed to acquire the lock (and therefore proceed to waiting on cv
) will be notified, the others will acquire the lock later and see ready true, bypassing cv
Upvotes: 2