I have implemented a class that allows me to synchronize threads with a condition variable. I have found conflicting information as to whether the notify_all should be done
There is no risk releasing the lock if the mutex was held in some interval between the state of the condition test changing and thr notification.
{
std::lock_guard<std::mutex> lk(_address_mutex);
_address = address;
}
_cv.notify_all();
here, the mutex was unlocked after _address
was changed. So no risk.
If we modify _address
to be atomic, naively this looks correct:
{
std::lock_guard<std::mutex> lk(_address_mutex);
}
_address = address;
_cv.notify_all();
but it is not; here, the mutex is released for the entire period between modifying the condition test and notification,
_address = address;
{
std::lock_guard<std::mutex> lk(_address_mutex);
}
_cv.notify_all();
The above, however, becomes correct again (if more than a little strange).
The risk is that the condition test will be evaluated with the mutex active (as false), then changed, then notification sent, then the waiting thread waits on a notification and releases the mutex.
waiting|signalling
lock
test
test changed
notification
listen+unlock
the above is an example of a missed notification.
So long as we have the mutex held anywhere after the test change and before the notification it cannot happen.