2009-11-26 10 views
8

abbiamo due thread che accedono a una lista tramite un metodo sincronizzato. PossiamoAssicurarsi che i blocchi sincronizzati Java siano stati presi in ordine?

a) affidamento sulla fase di esecuzione per fare in modo che ognuno di loro riceverà l'accesso al metodo basato sull'ordine hanno cercato di o

b) fa il VM seguire tutte le altre regole

c) c'è un modo migliore per serializzare le richieste?

Grazie mille!

+1

È abbastanza improbabile che sia davvero necessario questo requisito. Potresti scoprire che l'utilizzo di ReentrantLock (true) è notevolmente più lento rispetto all'esecuzione dell'intera operazione con sincronizzazione. –

risposta

17

No, sincronizzato darà accesso in qualsiasi ordine (dipende dall'implementazione JVM). Ciò potrebbe persino causare la morte dei thread in alcuni scenari.

È possibile garantire l'ordine utilizzando ReentrantLock (da Java 5.0) con l'opzione fair=true. (Lock lock = new ReentrantLock(true);)

+4

"sincronizzato darà accesso in ordine casuale (o chi è il più veloce ad afferrare il lucchetto)". L'ordine non è semplicemente specificato. È quasi certamente NON casuale, ed è dipendente dall'implementazione (e altamente improbabile) che il "primo" thread ottenga sempre il lock ... specialmente su un sistema multiprocessore. –

+2

Hai ragione, Stephen. Ma non è possibile inoltrare su un'implementazione specifica, quindi il programmatore deve aspettarsi un comportamento casuale. – Hardcoded

+1

L'ordine non è casuale né è garantito che sia casuale. Non appena un thread si blocca, può essere cambiato contesto in modo che non riproverà per un po ', quindi è possibile ottenere un thread tra molti ottenere il lock molte volte prima che un altro thread abbia la possibilità di svegliarsi. –

-1

Sì.

Se l'accesso alla lista avviene tramite un metodo sincronizzato, le richieste simultanee da più thread verranno serializzate.

+2

@Conrad. Non penso sia vero. Quando più thread sono in attesa di un monitor, ognuno di essi può essere assegnato in base all'implementazione. Non possiamo essere sicuri che il monitor verrà assegnato nell'ordine richiesto dai thread per esso. – Varun

+4

Stai rispondendo a una domanda sottilmente diversa che ciò che è stato chiesto. MrG sta chiedendo l'ordine di programmazione dei blocchi sincronizzati contestati, non se i blocchi sincronizzati sono rispettati. –

+0

Sì, anche se penso che non importi la maggior parte del tempo. –

10

No, non si può essere certi che due chiamate a un metodo sincronizzato si verificheranno nell'ordine. L'ordine non è specificato e dipende dall'implementazione.

Questo è definito nella sezione 17.1 Locks di JLS. Si noti che non viene detto nulla sull'ordine in cui i thread in attesa su un lucchetto dovrebbero ottenere l'accesso.

+0

Come la tua risposta, anche se non dire nulla non significa necessariamente che non ci sarà un ordine, quindi penso che dipenderà dall'implementazione. E suppongo che HotSpot/OpenJDK si basino sullo scheduler dei thread del sistema operativo. – user454322

+0

@ user454322 - questa è una valutazione equa. –

3

Non è possibile fare affidamento sull'ordine in cui viene chiamato il metodo particolare da ogni thread. Se è solo due thread può essere sì. Ma immagina se ci sono 3 thread e 1 thread già acquisiti. Gli altri 2 thread quando tentano di accedere attenderanno e ad ognuno di essi potrà essere concesso l'accesso, e questo non dipende dall'ordine in cui hanno chiamato questo metodo. Quindi, non è consigliabile fare affidamento sull'ordine.

+3

"Quindi, non è consigliabile fare affidamento sull'ordine." - E 'un eufemismo !! Direi che qualsiasi programma che fa affidamento su di esso è * sicuramente * non-portatile e * probabilmente * buggato sulla piattaforma su cui è stato implementato/testato! –

+0

@Stephen Non posso essere più d'accordo. – Varun

0

c) c'è un modo migliore per serializzare le richieste?

Stai per caso utilizzando l'elenco come una coda, ovvero il modello di utilizzo ha un aspetto simile a questo?

 
while (some condition) { 
    synchronized(theList){ 
     anItem = get and remove an element from theList 
    } 
    do some work with anItem 
} 

Se è così, si potrebbe voler dare un'occhiata all'interfaccia invece di utilizzare i propri schemi di bloccaggio BlockingQueue. Le implementazioni (come ArrayBlockingQueue) hanno impostazioni di equità e altro ancora.

0

Lascio sempre le sincronizzazioni al server delle applicazioni o al motore a meno che non si definisca la propria intensità

Problemi correlati