4

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?

Vasily
  • 235
  • 3
  • 14
  • 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`? – Red XIII Feb 26 '13 at 10:53
  • Sorry. This question was too unclear. I've rephrased it here: http://stackoverflow.com/questions/15085823/stdcondition-variablenotify-one-called-several-times-without-context-switc and flagged for remove. – Vasily Feb 26 '13 at 11:04

2 Answers2

4

§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(/*...*/);
ronag
  • 49,529
  • 25
  • 126
  • 221
  • What will happen if I place both notify_one() under the same mutex to prevent your scenario? – Vasily Feb 26 '13 at 08:17
  • 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()? – Vasily Feb 26 '13 at 08:21
  • 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. – Pavel P Oct 09 '19 at 21:30
1

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.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Sorry. It looks like my question was too unclear. I've rephrased it and asked again here: [link](http://stackoverflow.com/questions/15085823/stdcondition-variablenotify-one-called-several-times-without-context-switc) – Vasily Feb 26 '13 at 09:46