Looking at several videos and the documentation example, we unlock the mutex before calling the notify_all()
. Will it be better to instead call it after?
The common way:
Inside the Notifier thread:
//prepare data for several worker-threads;
//and now, awaken the threads:
std::unique_lock<std::mutex> lock2(sharedMutex);
_threadsCanAwaken = true;
lock2.unlock();
_conditionVar.notify_all(); //awaken all the worker threads;
//wait until all threads completed;
//cleanup:
_threadsCanAwaken = false;
//prepare new batches once again, etc, etc
Inside one of the worker threads:
while(true){
// wait for the next batch:
std::unique_lock<std::mutex> lock1(sharedMutex);
_conditionVar.wait(lock1, [](){return _threadsCanAwaken});
lock1.unlock(); //let sibling worker-threads work on their part as well
//perform the final task
//signal the notifier that one more thread has completed;
//loop back and wait until the next task
}
Notice how the lock2
is unlocked before we notify the condition variable - should we instead unlock it after the notify_all()
?
Edit
From my comment below: My concern is that, what if the worker spuriously awakes, sees that the mutex is unlocked, super-quickly completes the task and loops back to the start of while. Now the slow-poke Notifier finally calls notify_all(), causing the worker to loop an additional time (excessive and undesired).
lock2
will automatically unlock the mutex after the_conditionVar.notify_all();
so you don't need to call it explicitly at all, that's the common idiom IIRC. BTW, don't use a prefix underscore for any of your code, this is reserved for compiler and standard library implementations. – Pereswhile
. Now the slow-poke Producer finally callsnotify_all()
, causing consumer to loop an additional time. – Lux