2010-05-24 16 views
15

In Java, fare ReentrantLock.lock() e ReetrantLock.unlock() utilizzare lo stesso meccanismo di blocco di synchronized()?Miscelazione sincronizzata() con ReentrantLock.lock()

La mia ipotesi è "No", ma spero di sbagliarmi.

Esempio:

Immaginate che Thread 1 e filettatura 2 entrambi hanno accesso a:

ReentrantLock lock = new ReentrantLock(); 

Discussione 1 piste:

synchronized (lock) { 
    // blah 
} 

Discussione 2 piste:

lock.lock(); 
try { 
    // blah 
} 
finally { 
    lock.unlock(); 
} 

Assumere il thread 1 la sua parte prima, poi la discussione 2 prima che la discussione 1 sia terminata: Thread 2 attenderà che Thread 1 lasci il blocco synchronized() o proseguirà?

risposta

14

No, il thread 2 può lock() anche se il thread 1 è synchronized sullo stesso lock. Questo è ciò che il documentation ha da dire:

nota che le istanze di blocco sono solo oggetti normali e possono essere a loro volta utilizzato come il bersaglio in una sincronizzata dichiarazione. L'acquisizione del blocco monitor di un'istanza di blocco non ha una relazione specifica con il richiamo di uno qualsiasi dei metodi lock() di tale istanza. Si consiglia di evitare per evitare confusione in questo modo , tranne nella propria implementazione .

+0

Questo è quello che ho pensato. C'è un posto in cui ho bisogno di usare 'ReetrantLock.tryLock()', e speravo di farla franca 'sincronizzata' ovunque. Grazie. –

9

I due meccanismi sono diversi. Attuazione/prestazioni:

  • il meccanismo sincronizzato utilizza un meccanismo di blocco "incorporato" nella JVM; il meccanismo sottostante è soggetto alla particolare implementazione JVM, ma in genere utilizza una combinazione di un'istruzione compare-and-set operation (CAS) non elaborata per i casi in cui il blocco non è conteso più i meccanismi di blocco sottostanti forniti dal sistema operativo;
  • le classi di blocco come ReentrantLock sono fondamentalmente codificate in puro Java (tramite una libreria introdotta in Java 5 che espone le istruzioni CAS e la descheduling dei thread in Java) e quindi è un po 'più standardizzata tra i sistemi operativi e più controllabile (vedi sotto).

In alcune circostanze, i blocchi espliciti possono offrire prestazioni migliori. Se osservi questo comparison of locking mechanisms eseguito in Java 5, vedrai che in quel particolare test (più thread che accedono a un array), le classi di blocco esplicite configurate in modalità "sleale" (i triangoli giallo e ciano) consentono un throughput maggiore rispetto a quello normale sincronizzato (le frecce viola).

(Devo anche dire che le prestazioni del sincronizzato sono state migliorate nelle versioni più recenti di Hotspot, potrebbe non esserci molto nelle ultime versioni o addirittura in altre circostanze-- questo è ovviamente un test in un ambiente .)

Funzionalità-saggio:

  • il meccanismo sincronizzato fornisce funzionalità minima (è possibile bloccare e sbloccare, blocco è un'operazione tutto-o-niente, sei più soggetto alla algoritmo di scrittori OS deciso on), sebbene con il vantaggio della sintassi incorporata e di alcuni monitor incorporati nella JVM;
  • classi blocco esplicito forniscono un maggiore controllo, in particolare è possibile specificare un blocco di "equo", serratura con un timeout, ignorare se è necessario modificare behiour della serratura ...
0

Perché hai fatto l'equilibrio statico nella classe Account? Rimuovi statico e dovrebbe funzionare.

Inoltre, avere una domanda sull'utilizzo del thread. Nel tuo TestMain crei nuovi thread e assegni i runnable come WithdrawRequests & DepositRequests. Ma ancora una volta create nuovi thread all'interno dei costruttori di quei runnables. Questo farà sì che il metodo di esecuzione sia eseguito due volte!