Просматривая несколько видео и пример документации мы разблокируем мьютекс перед вызовом notify_all()
. Будет ли лучше вместо этого называть его после?
Общий способ:
Внутри потока уведомлений:
//prepare data for several worker-threads;
//and now, awaken the threads:
std::unique_lock<std::mutex> lock2(sharedMutex);
_threadsCanAwaken = true;
lock2.unlock();
_conditionVar.notify_all(); //awaken all the worker threads;
//wait until all threads completed;
//cleanup:
_threadsCanAwaken = false;
//prepare new batches once again, etc, etc
Внутри одного из рабочих потоков:
while(true){
// wait for the next batch:
std::unique_lock<std::mutex> lock1(sharedMutex);
_conditionVar.wait(lock1, [](){return _threadsCanAwaken});
lock1.unlock(); //let sibling worker-threads work on their part as well
//perform the final task
//signal the notifier that one more thread has completed;
//loop back and wait until the next task
}
Обратите внимание, что lock2
разблокируется до того, как мы уведомим переменную условия — должны ли мы вместо этого разблокировать его после notify_all()
?
Изменить
Из моего комментария ниже: Меня беспокоит то, что, если потребитель будет очень быстрым. Потребитель ложно просыпается, видит, что мьютекс разблокирован, завершает задачу и возвращается к началу while. Теперь медлительный производитель, наконец, вызывает notify_all(), в результате чего потребитель зацикливается еще раз.
lock2
автоматически разблокирует мьютекс после_conditionVar.notify_all();
, поэтому вам вообще не нужно вызывать его явно, это обычная идиома IIRC. Кстати, не используйте префикс подчеркивания для любого вашего кода, это зарезервировано для реализаций компилятора и стандартной библиотеки. - person πάντα ῥεῖ   schedule 25.09.2018while
. Теперь медлительный производитель, наконец, вызываетnotify_all()
, заставляя потребителя зацикливаться еще раз. - person Kari   schedule 25.09.2018