0

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 <[email protected]> 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; } 
14
  • 2
    Your condition predicate is data_ready, and you're modifying it in master_thread without the mutex, whos sole purpose is to protect it, latched. That in itself is wrong. Commented Jul 1, 2015 at 14:59
  • 1
    @mmostajab You started the slave threads. Whether they've each in-turn latched, checked, and entered-wait (thus unlatching) isn't particularly relevant so long as the predicate data is properly protected (which it currently is not in master). If you really want to ensure all slaves are sitting on the wait it is possible with a little more work, but frankly it is also fairly pointless. Commented Jul 1, 2015 at 15:19
  • 1
    "I like to make sure all slaves are on the wait" - why ? If the predicate data is properly managed it won't matter whether they're sitting on a cvar wait or not (which is somewhat the point of proper predicate management). Commented Jul 1, 2015 at 16:00
  • 1
    @mmostajab it will not happen at all, wait() suspends execution and unlocks mutex atomically. I think you are missing this point. So if slave will be suspended before wait() mutex will remain locked. Commented Jul 1, 2015 at 16:37
  • 1
    @mmostajab counter will not eliminate the problem, it is an answer how to count how many slave threads are waiting, for whatever reason you need it. If you still think you need to make sure all slaves are waiting to eliminate the problem discussed, you are wrong. Commented Jul 1, 2015 at 16:39

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is as accurate as I could/would have written it. The fundamental rule for cvars+mutexes is simple: Never change, nor even check, the predicate data state unless the predicate mutex is locked. The master thread is violating that fundamental rule. Upticked.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.