Domanda

Mi sono imbattuto in questo interessante paragrafo nel Aumenta la documentazione del thread oggi:

void wait(boost::unique_lock<boost::mutex>& lock)

...

  

Effetti: chiama atomicamente lock.unlock ()   e blocca il thread corrente. Il   il thread verrà sbloccato quando notificato da a   chiama a this- > notification_one () o   this- > notification_all () o spuratamente .   Quando il thread è sbloccato (per   qualunque sia la ragione), la serratura è   riacquistato invocando lock.lock ()   prima che la chiamata in attesa ritorni. Il   il blocco viene inoltre riattivato invocando   lock.lock () se la funzione termina con   un'eccezione.

Quindi quello che mi interessa è il significato della parola "spurdamente". Perché il thread dovrebbe essere sbloccato per motivi spuri? Cosa si può fare per risolvere questo problema?

È stato utile?

Soluzione

Questo articolo di Anthony Williams è particolarmente dettagliato .

  

I risvegli spuri non possono essere previsti:   sono essenzialmente casuali dal   punto di vista dell'utente. Tuttavia, loro   si verificano comunemente quando la libreria di thread   non può garantire in modo affidabile un'attesa   il thread non perderà una notifica.   Dal momento che una notifica persa sarebbe   rendere la variabile di condizione inutile,   la libreria di thread riattiva il thread   dalla sua attesa piuttosto che prendere il   rischio.

Sottolinea inoltre che non dovresti usare i sovraccarichi timed_wait che richiedono una durata e generalmente dovresti usare le versioni che accettano un predicato

  

Questo è il bug del principiante, e uno   che è facilmente superato con un semplice   regola: controlla sempre il tuo predicato in a   loop quando si attende con una condizione   variabile. Il bug più insidioso arriva   da timed_wait ().

Anche questo articolo di Vladimir Prus è interessante.

  

Ma perché abbiamo bisogno del ciclo while,   non possiamo scrivere:

if (!something_happened)
  c.wait(m);
  

Non possiamo. E la ragione killer è che l'attesa può   restituire senza alcuna chiamata di "notifica".   Questo si chiama risveglio spurio ed è   esplicitamente consentito da POSIX.   In sostanza, ritorna solo da "aspetta"   indica che i dati condivisi potrebbero   sono cambiati, quindi i dati devono essere   valutato di nuovo.

     

Va ??bene, quindi perché questo non è stato ancora risolto?   La prima ragione è che nessuno vuole   per risolverlo. Avvolgimento della chiamata per "attendere"   un loop è molto desiderato per diversi   altri motivi. Ma quei motivi   richiede una spiegazione, sebbene falsa   wakeup è un martello che può essere applicato   a qualsiasi studente del primo anno senza   fallire.

Altri suggerimenti

Questo post sul blog fornisce una ragione per Linux, in termini della chiamata di sistema futex che ritorna quando un segnale viene inviato a un processo. Purtroppo non spiega nient'altro (e anzi chiede maggiori informazioni).

La la voce di Wikipedia sui risvegli spuri (che sembra essere un concetto ampio, tra l'altro, non solo per aumentare) potrebbe interessarti anche tu.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top