I am running the following chunk of the code. This code is going to create 5 slave threads and 1 main thread. All slave threads are waited for the main thread to make the data ready and when the data gets ready, all slaves will notify to start processing.
My question is, it is possible that before the slave threads start waiting for the conditional_variable
, the main thread make the data ready and notify the waited threads. In this case, some threads which were waited will get the notification and start processing but the ones which were not waited, will starting waiting for a notification which will NEVER come.
If you run this example, this case won't happen but I am looking for a way to make sure that all the slave threads are waiting for the notification, then notifying them. Do you know how can I do that?
/*
Condition Variables - Many waiting threads
Shows how one condition variable can be used to notify multiple threads
that a condition has occured.
* Part of "Threading with Boost - Part IV: Condition Variables", published at:
http://antonym.org/boost
Copyright (c) 2015 Gavin Baker <gavinb@antonym.org>
Published under the MIT license, see LICENSE for details
*/
#include <cstdio>
#include <boost/thread.hpp>
boost::condition_variable data_ready_cond;
boost::mutex data_ready_mutex;
bool data_ready = false;
void master_thread()
{
printf("+++ master thread\n");
// Pretend to work
printf(" master sleeping...\n");
boost::chrono::milliseconds sleepDuration(750);
boost::this_thread::sleep_for(sleepDuration);
// Let other threads know we're done
printf(" master notifying...\n");
data_ready = true;
data_ready_cond.notify_all();
printf("--- master thread\n");
}
void slave_thread(int id)
{
printf("+++ slave thread: %d\n", id);
boost::unique_lock<boost::mutex> lock(data_ready_mutex);
while (!data_ready)
{
data_ready_cond.wait(lock);
}
printf("--- slave thread: %d\n", id);
}
int main()
{
printf("Spawning threads...\n");
boost::thread slave_1(slave_thread, 1);
boost::thread slave_2(slave_thread, 2);
boost::thread slave_3(slave_thread, 3);
boost::thread slave_4(slave_thread, 4);
boost::thread master(master_thread);
printf("Waiting for threads to complete...\n");
slave_1.join();
slave_2.join();
slave_3.join();
slave_4.join();
master.join();
printf("Done\n");
return 0;
}
You have race condition - setting flag and notifying slave threads is not atomic. So you just have to lock data_ready_mutex
before you are modifying data_ready
flag in main thread. This will eliminate race condition, slave thread either will see data_ready
false and go to wait on condition variable and will be notified, or it will acquire mutex lock only after data_ready
is set to true
and so it will not wait at all.