Сколько ожидающих потоков проснется в этом примере:
1-й поток:
void wakeUp2Threads()
{
std::unique_lock<std::mutex> lock(condvar_mutex);
condvar.notify_one();
condvar.notify_one();
}
2-й поток:
{
std::unique_lock<std::mutex> lock(condvar_mutex);
condvar.wait(lock); <- 2nd thread has entered here before 1st thread entered wakeUp2Threads.
}
3-я нить (так же, как 2-й):
{
std::unique_lock<std::mutex> lock(condvar_mutex);
condvar.wait(lock); <- 3rd thread has entered here before 1st thread entered wakeUp2Threads.
}
Есть ли гарантия, что в этом примере оба уведомления будут доставляться в разные потоки, а не в один и тот же поток несколько раз?
Т.е. что означает notify_one ():
1) notify one thread, no matter has it been already notified (but has not been woken up yet), or not. (* see note)
or
2) notify one thread, but only this one, which has not been notified yet.
(*) Обращать внимание! Я не говорю здесь о сценарии «ожидающий поток уже был уведомлен где-то в прошлом, проснулся, сделал некоторые вещи и снова вошел в condvar.wait ()» — конечно, в этом случае могут возникнуть несколько процедур notify_one () одна и та же нить снова и снова.
Я говорю о другом случае:
notify_one () уведомил ожидающий поток о пробуждении, но ДО того, как этот ожидающий поток получил временной интервал от планировщика ядра и продолжил выполнение — снова вызывался другой notify_one (). Возможно ли, что второе уведомление будет доставлено в тот же поток снова, пока оно еще не проснулось от первого уведомления?
notify_one
вызов атомарно разблокирует один поток. Это означает, что при повторном вызове он не может разблокировать тот же поток, поскольку он больше не блокируется.
Это указано в стандарте в разделах 30.5 / 3 и 30.5.1 / 7.
Других решений пока нет …