Нужно ли синхронизировать std::condition_variable/condition_variable_any::notify_one
?Нужно ли синхронизировать std :: condition_variable/condition_variable_any :: notify_one
Насколько я могу судить, если утеряны уведомления допустимы - нормально позвонить notify_one
не защищен (например, mutex).
Например, я видел следующие модели использования (извините, не помню где):
{
{
lock_guard<mutex> l(m);
// do work
}
c.notify_one();
}
Но, я осмотрел libstdC++ источники, и я вижу:
condition_variable::notify_one
void condition_variable::notify_one() noexcept
{
int __e = __gthread_cond_signal(&_M_cond);
// XXX not in spec
// EINVAL
if (__e)
__throw_system_error(__e);
}
и condition_variable_any::notify_one:
void condition_variable_any::notify_one() noexcept
{
lock_guard<mutex> __lock(_M_mutex);
_M_cond.notify_one();
}
А вот расположение condition_variable_any:
class condition_variable_any
{
condition_variable _M_cond;
mutex _M_mutex;
// data end
Т.е. это просто тонкая обертка вокруг condition_variable + mutex.
Итак, вопросы:
- ли потокобезопасный не защищать
notify_one
от мьютекса для любогоcondition_variable_any
илиcondition_variable
? - Почему реализация condition_variable_any использует дополнительные мьютексы?
- Почему реализация
condition_variable_any::notify_one
иcondition_variable::notify_one
отличается? Возможно,condition_variable::notify_one
требует ручной защиты, ноcondition_variable_any::notify_one
нет? Это ошибка libstdC++?
Спасибо! Это очень помогло мне. Эсперично ответьте на 2 и 3 - хороший момент об атомарности и внутреннем материале, который все равно использует мьютекс. Кстати, вы можете добавить ссылку на pthread_cond_wait http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_wait.html, чтобы показать, что наиболее распространенная реализация работает только с ее собственным мьютексом во внутренних компонентах. Не могли бы вы прояснить, что именно вы имеете в виду: «Там есть довольно тонкий код». – qble
Относительно 1. - может ли незаблокирован условие_вариабельный :: notify_one привести к пропущенным уведомлениям? То есть thread # 1 делает работу под мьютексом, посылает результат, разблокирует мьютекс, [тем временем] поток # 2 блокирует мьютекс, но еще не вызвал wait, [тем временем] поток # 1 вызывает notify_one, [тем временем] поток # 2 вызывает wait - уведомление теряется. – qble
Это не потерянное уведомление, это ожидающий поток, не проверяющий предикат условия перед ожиданием. Блокировка мьютекса не помогает этой ситуации, уведомление все равно может появиться до того, как ожидающий поток заблокирует мьютекс. Вы ** должны ** проверять связанный предикат при ожидании переменной состояния –