std::condition_variable::notify_one() called twice [duplicate]
Asked Answered
J

2

5

How many waiting threads will wake up if I call std::condition_variable::notify_one() twice without any time interval, like this:

{
    std::unique_lock<std::mutex> lock(condvar_mutex);

    condvar.notify_one();
    condvar.notify_one();
}

Is there any guarantee that these notifications will be delivered to different threads, not the same thread several times?

Jorgan answered 26/2, 2013 at 8:1 Comment(2)
You are basically asking whether a notified thread (and locked on mutex) can be notified once more as it's not waiting anymore on the cond_var and is rather blocked on a condvar_mutex?Denti
Sorry. This question was too unclear. I've rephrased it here: #15086323 and flagged for remove.Jorgan
S
5

§30.5.1.7: If any threads are blocked waiting for *this, unblocks one of those threads.

There is no guarantee that it's different threads, just that it's one thread. During the time between the two notify_one calls it is possible that the same thread that was waked with the first notify_one is re-blocked.

e.g. In the following example it is not guaranteed whether thread 3 will wake or not (disregard spurious wakes for this example).

- thread 1:

1    condvar.notify_one();
- 3 and 4 could run here.
2    condvar.notify_one();

- thread 2:

3    condvar.wait(/*...*/);
4    condvar.wait(/*...*/);

- thread 3:

5    condvar.wait(/*...*/);
Soapsuds answered 26/2, 2013 at 8:7 Comment(3)
What will happen if I place both notify_one() under the same mutex to prevent your scenario?Jorgan
Maybe I've asked the wrong question. In fact, I was wondering - is there any possibility to wake up just one condvar.wait(...) after calling notify_one() twice. So, let's suppose there is no 'thread 3' in your example. Is it possible that second thread will be notified only once and will be blocked in the second condvar.wait()?Jorgan
It's not possible that the same thread that was woken up with the first call get re-blocked. In fact, it's not even possible that any thread is woken up after the first notify.Jasminejason
C
2

I assume that condvar_mutex is the correct mutex for the condvar.

It's not possible for both notifications to be delivered to the same thread. The reason is that you call notify_one twice while holding the mutex. So whichever thread is unblocked first, there's no way it can acquire the mutex, so it can't return from wait. It can't even throw an exception from wait_for without first acquiring the mutex.

Since it can't get out of its wait, there's no way it can get back onto the list of waiters before the second notify_one is called.

So, your code unblocks up to two threads blocked on the condvar, if there are that many. If there are fewer then the additional notifications have no effect.

Chiton answered 26/2, 2013 at 9:32 Comment(1)
Sorry. It looks like my question was too unclear. I've rephrased it and asked again here: linkJorgan

© 2022 - 2024 — McMap. All rights reserved.