std::condition_variable cv;
std::mutex m_cnt;
int cnt = 0;
void producer() {
std::unique_lock<std::mutex> ul(m_cnt);
cnt++;
cv.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void consumer() {
std::unique_lock<std::mutex> ul(m_cnt);
cv.wait(ul, [] {return cnt > 0;}); // ---> Here
cnt--;
}
In the following example, what happens in cv.wait()
? It has been notified by producer
, but doesn't have the m_cnt
(lock) to move further. Once the consumer
is "notified" does it keep on trying to acquire the lock indefinitely?
I'm going to answer the question in the title first:
Question:
What happens when a conditional variable gets notified but doesn't have the lock yet?
Answer: The notification is missed. If a (un-timed) wait
is initiated after the only notification, it might wait forever. It also might not because spurious wakes are allowed (waking for no reason).
However: The code you posted does not have this problem.
Details:
Let's say (as you imply) that producer()
runs first.
mutex
.cnt
.cv
, with no one waiting on it, so that notification is missed.mutex
.And let's say that consumer()
starts running any time after step 1 in producer()
:
mutex
until producer()
releases it.mutex
.cv.wait(ul, [] {return cnt > 0;})
.At this point it is instructive to look at the spec for this function.
Effects: Equivalent to:
while (!pred())
wait(lock);
Note that !pred()
is called before a wait actually happens! The predicate will find that cnt
has already been incremented by producer()
and thus skip the wait
.
So the missed notification is immaterial.
cnt
.mutex
.If consumer()
runs first, then it will enter the wait
and producer()
will have either not started yet, or it will be blocked on the mutex
until consumer()
enters the wait
. Then producer()
will increment cnt
(step 2) and continue through step 5. consumer()
will receive the notification and wait until producer()
's step 5 is done before proceeding with consumer()
's step 4.