Devo sincronizzare std::condition_variable/condition_variable_any::notify_one
?Devo sincronizzare std :: condition_variable/condition_variable_any :: notify_one
Per quanto posso vedere, se la perdita di notifiche è accettabile, è corretto chiamare notify_one
non protetto (da mutex ad esempio).
Per esempio, ho visto seguendo modelli di utilizzo (mi dispiace, non ricordo dove):
{
{
lock_guard<mutex> l(m);
// do work
}
c.notify_one();
}
Ma, ho controllato le fonti libstdC++, e vedo:
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);
}
e condition_variable_any::notify_one:
void condition_variable_any::notify_one() noexcept
{
lock_guard<mutex> __lock(_M_mutex);
_M_cond.notify_one();
}
E qui è il layout di condition_variable_any:
class condition_variable_any
{
condition_variable _M_cond;
mutex _M_mutex;
// data end
Vale a dire è solo un involucro sottile attorno a condition_variable + mutex.
Quindi, domande:
- E 'thread-safe per non protegge
notify_one
da mutex sia percondition_variable_any
ocondition_variable
? - Perché l'implementazione di condition_variable_any utilizza mutex aggiuntivo?
- Perché l'implementazione di
condition_variable_any::notify_one
econdition_variable::notify_one
differisce? Forsecondition_variable::notify_one
richiede la protezione manuale ma non lo è ilcondition_variable_any::notify_one
? È un bug libstdC++?
Grazie! Questo mi ha aiutato molto. Esattamente rispondo a 2 e 3 - buon punto sull'atomicità, e cose interiori che usano comunque il mutex. A proposito, puoi aggiungere il link a pthread_cond_wait http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_wait.html per mostrare che l'implementazione più comune funziona solo con il proprio mutex in internals. Potresti per favore chiarire cosa intendi esattamente in "c'è un codice piuttosto sottile lì". – qble
Riguardo a 1. - può condizione non bloccata condition_variable :: notify_one portare a notifiche mancate? Cioè thread # 1 fa il lavoro sotto mutex, invia risultato, sblocca mutex, [nel frattempo] il thread # 2 blocca mutex ma non ancora chiamato wait, [nel frattempo] thread # 1 chiama notify_one, [nel frattempo] thread # 2 chiama wait - la notifica è persa. – qble
Questa non è una notifica persa, è il thread in attesa che non controlla il predicato sulla condizione prima di attendere. Il blocco del mutex non aiuta questa situazione, la notifica potrebbe ancora arrivare prima che il thread in attesa blocchi il mutex. È ** necessario ** controllare il predicato associato quando si attende una variabile di condizione –