La spiegazione dei risvegli spuri suona come un bug che non vale la pena correggere, giusto?


30

Secondo l'articolo di Wikipedia su Wakeups spuri

"un thread potrebbe essere risvegliato dal suo stato di attesa anche se nessun thread ha segnalato la variabile di condizione".

Mentre conosco questa "caratteristica", non ho mai saputo cosa l'abbia effettivamente causata fino allo stesso articolo

"Le riattivazioni spurie possono sembrare strane, ma su alcuni sistemi multiprocessore, rendere completamente prevedibile la riattivazione delle condizioni potrebbe rallentare sostanzialmente tutte le operazioni delle variabili di condizione."

Sembra un bug che non vale la pena risolvere, giusto?


1
correlate: "Perché pthread_cond_wait ha risvegli spuri?", stackoverflow.com/questions/8594591/…
Florian Castellane,

Risposte:


39

TL; DR Assumption ("contratto") di risvegli spuri è una decisione architettonica ragionevole presa per consentire implementazioni realisticamente robuste di sheduler di filo.

Le "considerazioni sulle prestazioni" sono irrilevanti qui, sono solo incomprensioni che sono diventate diffuse a causa di aver dichiarato in un riferimento autorevole pubblicato. (i riferimenti autorevoli potrebbero avere errori, sai - basta chiedere a Galileo Galilei ) L' articolo di Wikipedia mantiene il riferimento alla nota che hai citato solo perché corrisponde perfettamente alle loro linee guida formali per citare il riferimento pubblicato.

Una ragione molto più convincente per introdurre il concetto di risvegli spuri è fornita in questa risposta a SO che si basa su ulteriori dettagli forniti in una (versione precedente) di questo stesso articolo:

L' articolo di Wikipedia sui risvegli spuri ha questo compito:

La pthread_cond_wait()funzione in Linux è implementata usando la futexchiamata di sistema. Ogni chiamata di sistema bloccante su Linux ritorna bruscamente con EINTRquando il processo riceve un segnale. ... pthread_cond_wait()non è possibile riavviare l'attesa perché potrebbe mancare un vero risveglio nel poco tempo in cui era fuori dalla futexchiamata di sistema ...

Pensaci ... come qualsiasi altro codice, lo scheduler dei thread potrebbe subire un blackout temporaneo a causa di qualcosa di anormale nell'hardware / software sottostante. Naturalmente, occorre prestare attenzione perché questo avvenga raro come possibile, ma dal momento che non c'è alcuna cosa come software robusto 100% è ragionevole supporre questo può accadere e prendersi cura sul recupero di grazia nel caso in cui se scheduler rileva tale (ad esempio, osservando i battiti del cuore mancanti ).

Ora, come potrebbe recuperare lo scheduler, tenendo conto del fatto che durante il blackout potrebbero mancare alcuni segnali destinati a notificare i thread in attesa? Se lo scheduler non fa nulla, i thread "sfortunati" citati si bloccheranno, aspettando per sempre - per evitarlo, lo scheduler invierebbe semplicemente un segnale a tutti i thread in attesa.

Ciò rende necessario stabilire un "contratto" per cui il thread in attesa può essere notificato senza motivo. Per essere precisi, ci sarebbe un motivo - blackout dello scheduler - ma poiché il thread è progettato (per una buona ragione) per essere ignaro dei dettagli dell'implementazione interna dello scheduler, è probabile che questo motivo sia meglio presentarlo come "spurio".


Dal punto di vista del thread, questo in qualche modo assomiglia a una legge di Postel (aka principio di robustezza ),

sii prudente in ciò che fai, sii liberale in ciò che accetti dagli altri

L'assunzione di risvegli spuri costringe il thread a essere conservativo in ciò che fa : imposta la condizione quando notifica altri thread e liberale in ciò che accetta : controlla la condizione al ritorno dall'attesa e ripeti l'attesa se non è ancora presente.


10
Ugh ... La legge di Postel ... il motivo per cui HTML e tutti i tipi di tecnologie web hanno messo così tanta merda in loro (es. Accettazione HTML di nidificazione di tag errati). A parte questo, buona risposta.
Thomas Eding,

3
La legge di Postel è il motivo per cui molti bug non vengono rilevati per anni perché ehi, anche se la tua funzione restituisce un output errato, l'app sembra funzionare ancora! La migliore invenzione di sempre.
Pacerier,

2
@Pacerier: la funzione che restituisce un output errato non segue la legge di Postel (parte conservativa).
YvesgereY,

@Pacerier: OTOH, che richiede che altri componenti siano rigorosi in modo che i bug possano essere individuati in precedenza è una posizione interessante, che si basa sul principio "Fail Fast" e sul design "Contract Based".
YvesgereY,

1

Non vale la pena aggiustare poiché il codice chiamante dovrebbe usare lo stesso trattamento (verificando le condizioni) comunque, al fine di gestire le condizioni di gara.

Un trattamento per due problemi, che riassumo come segue:

Sveglia spuria: il thread di attesa è programmato prima che la condizione sia stabilita.
Sovraccarico forzato: il thread di attesa è programmato dopo che la condizione è stata nuovamente falsificata.

Dal momento che potrebbe succedere in seguito, alcuni sono arrivati ​​al punto di introdurre un risveglio spurio nel contratto:

  • applicare le buone pratiche richiedendo cicli predicati.
  • per dare un po 'di libertà per l'implementazione dello scheduler (inclusa un'opzione di ripristino di emergenza, come indicato da @gnat).

Riferimento SO


Vorrei fare +1 su questo, ma per l'idea che qualcuno abbia introdotto intenzionalmente risvegli spuri al fine di indurre i chiamanti ad aggiungere cicli predicati per affrontare il sonno forzato. Lo trovo inconcepibile.
Ruakh

"L'intenzione era quella di forzare il codice corretto / robusto richiedendo cicli predicati." Vedi il link fornito.
YvesgereY,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.