In a multithreaded environment, we have the following two functions:
std::mutex mtx;
std::condition_variable cv;
void waiter()
{
std::unique_lock<std::mutex> lck(mtx);
//...
cv.wait(lck);
//...
}
void notifier()
{
std::unique_lock<std::mutex> lck(mtx);
//...
cv.notify_one();
}
Assume that the waiter executes first and then waits on the condition_variable. Then the notifier executes and notifies the waiter. The waiter tries to reacquire the mutex after the notifier has released it.
Question: Is it possible that some other thread locks the mutex right after the notifier has released it but still before the waiter gets it? If yes, what has to be done so that this cannot happen? And if yes, I also don't understand the purpose of condition_variable. The purpose should be to block a thread until some condition is fulfilled. But if, after the condition is fulfilled and the thread has been woken up, there is the chance that again the condition is not fulfilled, what's the point?
Is it possible that some other thread locks the mutex right after the notifier has released it but still before the waiter gets it?
Yes.
If yes, what has to be done so that this cannot happen?
Nothing.
And if yes, I also don't understand the purpose of condition_variable. The purpose should be to block a thread until some condition is fulfilled. But if, after the condition is fulfilled and the thread has been woken up, there is the chance that again the condition is not fulfilled, what's the point?
It's even more complicated. The thread can be woken up if the condition variable was not notified at all. This is called spurious wakeup (doc).
The point of condition variable is to block a thread until some other thread notifies it. In order to address the "condition is not fulfilled when the waiting thread gets a chance to execute" issue usually the waiting thread waits in a loop until the condition is fulfilled. The standard library even has a shortcut for that, there is a void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
overload that does exactly that. See the doc.