2012-02-27 16 views
5

Sto pensando qui: Se hai 2 thread che eseguono operazioni FAST che devono essere sincronizzate, non è un approccio non bloccante più veloce/migliore di un approccio di blocco/contesto?Blocchi di blocco contro blocchi non bloccanti

Con non-blocking voglio dire qualcosa come:

while (true) { se (checkAndGetTheLock)() break; }

L'unica cosa che riesco a pensare è la fame (con CPU bruciata) se ci sono troppi fili che si aggirano intorno al lucchetto.

Come bilanciare un approccio rispetto all'altro?

+0

Quante operazioni di blocco farete per core della CPU al secondo? – usr

+0

AFAIK, la JVM fa questa ottimizzazione per te se non c'è nessuna contesa sul blocco (che dovrebbe essere il caso se l'operazione è veloce) –

+0

@JB Nizet: Penso che tu debba prendere questa decisione da solo usando sincronizzato contro ReentrantLock. – chrisapotek

risposta

5

Ecco cosa Java Concurrency in Practice dice su questo argomento:

La JVM può implementare il blocco sia tramite spin-attesa (più volte cercando di acquisire il blocco fino a quando non riesce) o bysuspending il bloccato passare attraverso il sistema operativo. Che è più efficiente dipende dalla relazione tra l'overhead dell'interruttore di contesto e il tempo fino a quando il blocco diventa disponibile; lo spin-waiting è preferibile per brevi attese e la sospensione è preferibile per lunghe attese. Alcune JVM scelgono tra le due in modo adattivo in base ai dati di profilazione delle passate attese volte, ma la maggior parte semplicemente sospende i thread in attesa di un blocco.

Ed anche (che è, IMO, il punto più importante):

Non ti preoccupare eccessivamente circa il costo della sincronizzazione uncontended. Il meccanismo di base è già abbastanza veloce e le JVM possono eseguire ulteriori ottimizzazioni che riducono o eliminano ulteriormente il costo. Invece, concentrare gli sforzi di ottimizzazione sulle aree in cui si verifica effettivamente la contesa di blocco .

+0

Non mi fiderei del fatto che "Alcune JVM scelgono tra le due in modo adattivo in base ai dati di profilazione dei tempi di attesa passati, ma la maggior parte semplicemente sospende i thread in attesa di un blocco." Ma non puoi mai sapere di cosa siano capaci quelle JVM hotspot moderne. Penserei che il blocco sincronizzato e ReentrantLock sia in attesa. Ma se possono cambiarsi l'un l'altro in fase di esecuzione, non ne sono sicuro. – chrisapotek

+1

Dove hai letto che ReentrantLock è occupato-in attesa? Se lo facesse, metterebbe la JVM in ginocchio per lunghe attese. La javadoc dice: * Un'esclusione reciproca rientrante Blocca con lo stesso comportamento di base e semantica del blocco monitor implicito acceduto usando i metodi e le istruzioni sincronizzati, ma con capacità estese. * –

+0

Posso sbagliarmi, ma sfogliando il codice sorgente l'ho pensato era il suo approccio: http://fuseyism.com/classpath/doc/java/util/concurrent/locks/AbstractQueuedSynchronizer-source.html NOOOOO! La JVM NON usa ReentrantLock per le sue cose interne. – chrisapotek

1

Beh, l'unico modo per essere sicuri è testarlo. Quando si tratta di multithreading e performance non si può semplicemente assumere.

+0

Questa risposta è corretta e non dovrebbe essere downvoted. – usr

+0

@usr bene, perché non lo hai poi svalutato? Sono stato fortemente tentato di svenderlo due volte, ma sarebbe ingiusto su M Platvoet. –

+0

L'ho svalutato. C'è un annullamento del downvote. – usr