2010-04-19 14 views
9

Per chiarire la terminologia, la resa è quando il thread abbandona la sua porzione temporale. La mia piattaforma di interesse è i thread POSIX, ma penso che la domanda sia generale.Multithreading, quando cedere rispetto al sonno

Supponiamo di avere un modello consumatore/produttore. Se voglio strozzare il consumatore o il produttore, che è meglio usare, dormire o cedere? Sono principalmente interessato all'efficienza dell'uso di entrambe le funzioni.

+1

Né si desidera bloccare. Google "buffer limitato". –

risposta

9

Il modo "giusto" di codificare un produttore/consumatore è di aspettare che il consumatore i dati del produttore. È possibile ottenere ciò utilizzando un oggetto di sincronizzazione come un Mutex. Il consumatore sarà Wait sul mutex, che lo bloccherà dall'esecuzione finché i dati non saranno disponibili. A sua volta, il produttore segnalerà il mutex quando i dati sono disponibili, il che riattiva il thread del consumatore in modo che possa iniziare l'elaborazione. Questo è più efficiente rispetto sleep sia in termini di:

  • utilizzo della CPU (nessun cicli si sprecano), e
  • tempo di esecuzione (esecuzione inizia non appena sono disponibili i dati, non quando un thread è in programma a svegliarsi su).

Detto questo, ecco un'analisi del rendimento rispetto al sonno che hai richiesto. Potrebbe essere necessario utilizzare tale schema se per qualche motivo attendere l'output non è fattibile:

Dipende da quanto traffico si sta ricevendo - se i dati vengono costantemente ricevuti ed elaborati, si potrebbe considerare di fare un rendimento. Tuttavia nella maggior parte dei casi ciò si tradurrà in un ciclo "occupato" che trascorre la maggior parte del tempo svegliando inutilmente il thread per verificare se qualcosa è pronto.

Probabilmente vorrai dormire per un breve periodo di tempo (forse per meno di un secondo, usando usleep) O meglio ancora usare un oggetto di sincronizzazione come un mutex per segnalare che i dati sono disponibili.

+0

sleep può sospendere l'esecuzione solo in secondi, il nanosleep può sospendere l'esecuzione in frazioni di secondo. – Ernelli

+0

@erneli che è dettagli di implementazione. – Anycorn

+0

Mi riferivo alla raccomandazione di Justin di usare il sonno per un periodo di tempo inferiore a un secondo. Ma il metodo corretto è ovviamente utilizzare la sincronizzazione. – Ernelli

1

Una buona ragione per dormire invece di rendimento è quando c'è troppa contesa in una specifica sezione critica. Diciamo per esempio che si tenta di acquisire due serrature e c'è un sacco di contesa su entrambe le serrature. Qui puoi usare il sonno per utilizzare un backoff esponenziale. Ciò consentirebbe a ogni tentativo fallito di pseduo di eseguire il backup in modo casuale per consentire ad altri thread di avere successo.

La cessione in questa situazione non è di grande aiuto in quanto la prospettiva di un backoff casuale può aumentare la probabilità che non si verifichino iniezioni di thread.

Modifica: Anche se so che questo non è necessariamente java specifico. L'implementazione di Java di Thread.sleep(0) ha lo stesso effetto di Thread.yield() A quel punto è più una questione di stile.

10

dormire e cedere non è la stessa cosa. Quando si chiama sleep il processo/thread da alla CPU un altro processo/thread per il tempo specificato.

yield cede la CPU a un altro thread, ma potrebbe tornare immediatamente se non ci sono altri thread che attendono la CPU.

Quindi, se si desidera limitare il regime, ad esempio durante lo streaming di dati a intervalli regolari, la funzione da utilizzare è la modalità sleep o nanosleep.

Se è necessaria la sincronizzazione tra produttore/consumatore, è necessario utilizzare un'attesa mutex/condizionale.

0

In Java, alcune implementazioni JVM trattano Thread.yield() come no-op, il che significa che potrebbe non avere alcun effetto. Chiamare Thread.sleep() non significa necessariamente che lo scheduler dovrebbe fornire la CPU a un altro thread; anche questo dipende dall'implementazione. Può passare da un contesto all'altro a un altro thread in attesa oppure no per ammortizzare il costo associato al context-switch.