2009-06-26 13 views
176

Vedere varie domande relative al blocco e (quasi) trovare sempre il termine "loop a causa di scatti spuri" Mi chiedo, qualcuno ha mai provato un tale tipo di attivazione (presupponendo un ambiente hardware/software decente per esempio)?Le sveglie spurie si verificano effettivamente?

Conosco il termine "spurio": nessun motivo apparente ma quali possono essere le ragioni di questo tipo di evento?

(Nota: Non sto mettendo in discussione la pratica di loop.)

Edit: Una domanda aiuto (per coloro che amano gli esempi di codice):

Se ho il programma seguente , e io eseguo:

public class Spurious { 
    public static void main(String[] args) { 
     Lock lock = new ReentrantLock(); 
     Condition cond = lock.newCondition(); 
     lock.lock(); 
     try { 
      try { 
       cond.await(); 
       System.out.println("Spurious wakeup!"); 
      } catch (InterruptedException ex) { 
       System.out.println("Just a regular interrupt."); 
      } 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

cosa posso fare per svegliare questa await fino spurio senza aspettare per sempre per un evento casuale?

risposta

175

La Wikipedia article on spurious wakeups ha questo bocconcino:

La funzione pthread_cond_wait() in Linux è implementato utilizzando la chiamata di sistema futex. Ogni chiamata al sistema di blocco su Linux ritorna improvvisamente con EINTR quando il processo riceve un segnale. ... pthread_cond_wait() non è in grado di riavviare l'attesa perché potrebbe perdere una vera ripresa nel poco tempo che era fuori dalla chiamata di sistema futex. Questa condizione di gara può essere evitata solo dal chiamante che verifica un invariante. Un segnale POSIX genererà quindi una sveglia spuria.

Sommario: Se un processo di Linux è segnalato i suoi thread in attesa sarà ogni godere di una bella, calda spuria sveglia.

Lo compro. È una pillola più facile da inghiottire rispetto alla ragione tipicamente vaga "è per le prestazioni" spesso data.

+11

Migliore spiegazione qui: http://stackoverflow.com/questions/1461913/does-c-monitor-wait-suffer-from-spurious-wakeups/1461956#1461956 – Gili

+3

Questo sblocco EINTR è vero per tutte le chiamate di sistema bloccanti derivate da Unix sistemi. Ciò ha reso il kernel molto più semplice, ma i programmatori dell'applicazione hanno acquistato il fardello. –

+1

Pensavo che pthread_cond_wait() e gli amici non potessero restituire EINTR, ma restituire zero se spulturalmente svegliato? Da: http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_wait.html "Queste funzioni non restituiscono un codice di errore di [EINTR]." – gubby

8

Cameron Purdy ha scritto un blog post un po 'indietro di essere colpito dal problema di sveglia spuria. Quindi sì, succede

Sto indovinando che è nelle specifiche (come una possibilità) a causa delle limitazioni di alcune delle piattaforme su cui viene distribuito Java? anche se potrei sbagliarmi!

+5

http://www.jroller.com/cpurdy/entry/java_supplies_apologies_to_weird – akarnokd

+0

Ho letto il post e mi ha dato un'idea sull'avere test di unità per testare la conformità di un'applicazione al paradigma di looping-wait risvegliandolo in modo casuale/deterministico . O è già disponibile da qualche parte? – akarnokd

+0

Un'altra domanda su SO: "Esiste una VM * strict * che può essere utilizzata per i test?". Mi piacerebbe vederne uno con una rigida memoria locale - non penso che esistano ancora –

20

Ho un sistema di produzione che presenta questo comportamento. Un thread attende un segnale che c'è un messaggio nella coda. Nei periodi di punta, fino al 20% dei wakeup sono spuri (cioè quando si sveglia non c'è nulla nella coda). Questo thread è l'unico consumatore dei messaggi. Funziona su una scatola Linux 8 SLES-10 ed è costruito con GCC 4.1.2. I messaggi provengono da un'origine esterna e vengono elaborati in modo asincrono perché vi sono problemi se il mio sistema non li legge abbastanza velocemente.

7

Solo per aggiungere questo. Sì, succede e ho passato tre giorni a cercare la causa di un problema multi-thread su un computer a 24 core (JDK 6). 4 di 10 esecuzioni hanno sperimentato questo senza alcun modello. Questo non è mai successo su 2 core o 8 core.

Ha studiato materiale online e questo non è un problema Java, ma un comportamento generale raro ma atteso.

+0

Ciao ReneS, stai sviluppando l'app? Fa (ha) ha un metodo wait() che chiama mentre controlla il ciclo di condizioni esterne come è suggerito in java doc http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html# aspetta% 28% 29? – gumkins

+0

Ho scritto su di esso e sì la soluzione è un ciclo while con un controllo delle condizioni. Il mio errore è stato il ciclo mancante ... ma così ho imparato a conoscere questi risvegli ... mai su due core, spesso su 24corsi https://blog.xceptance.com/2011/05/06/spurious-wakeup-the-rare -evento/ – ReneS

11

Per rispondere alla domanda nella titolazione - Sì! lo fa happen.Though il Wiki article menzioni un buon affare su wakeups spuri una bella spiegazione per la stessa che mi sono imbattuto è il seguente -

pensate un po '... come qualsiasi codice, filo di pianificazione che si verifichi blackout temporaneo a causa di qualcosa di anormale che accade nell'hardware/software sottostante. Naturalmente, è necessario fare attenzione affinché ciò accada il più raramente possibile, ma poiché non esiste software affidabile al 100%, è ragionevole presumere che ciò possa accadere e occuparsi del ripristino agevole nel caso in cui lo scheduler lo rilevasse (ad es. osservando i battiti del cuore mancanti).

Ora, come è possibile ripristinare lo scheduler, tenendo conto che durante il blackout potrebbero mancare alcuni segnali destinati a notificare thread in attesa? Se lo scheduler non fa nulla, le discussioni "sfortunate" si bloccheranno, aspettando per sempre - per evitare ciò, lo scheduler semplicemente invierà un segnale a tutti i thread in attesa.

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

Stavo leggendo questa risposta dal Source e l'ho trovato abbastanza ragionevole. Leggi anche

Spurious wakeups in Java and how to avoid them.

Problemi correlati