2013-01-14 12 views
6

Ho conosciuto un Hashtable è sincronizzato, ma perché il suo metodo get() è sincronizzato?Hashtable: perché il metodo get viene sincronizzato?

È solo un metodo di lettura?

+7

Perché deve essere sincronizzato con i metodi put. –

+0

Non ho capito. C'è solo un campo di classe - la tabella deve essere sincronizzata, ma ottenere il metodo nessuna operazione di scrittura? – user1626860

+1

Entrambe le operazioni 'put' e' get' devono essere sincronizzate tra loro ... e lo sono. –

risposta

0

Hashtable è sincronizzato significato tutta la classe è thread-safe

All'interno del Hashtable, metodo non solo ottenere() è sincronizzato ma anche molti altri metodi sono. E in particolare il metodo put() è sincronizzato come ha detto Tom.

Un metodo di lettura deve essere sincronizzato come metodo di scrittura perché garantisce la visibilità e la coerenza della variabile.

+1

Questo non ha senso. Hashtable è una classe e non puoi dichiarare una classe come "sincronizzata". E infatti, "Hashtable" non è interamente thread-safe. (In particolare, l'iterazione non è thread-safe nel modo in cui ci si potrebbe aspettare ...) –

+0

@StephenC Sono d'accordo con ciò che hai detto dopo aver letto [thread-safe] (http://vanillajava.blogspot.hk/2011/ 06/thread-safety-issues-with-vector-and.html) Grazie! – Hitman47

1

Dai un'occhiata al codice sorgente di Hashtable e puoi pensare a molte condizioni di gara che possono causare problemi in uno get() non sincronizzato.

(sto leggendo JDK6 codice sorgente)

Ad esempio, un rehash() creerà un array vuoto, e assegnare all'istanza var table, e mettere le voci dal vecchio tavolo a quello nuovo. Pertanto se il tuo get si verifica dopo l'assegnazione dell'array vuoto, ma prima di inserire effettivamente le voci in esso, non puoi trovare la tua chiave nemmeno nella tabella.

Un altro esempio è che c'è un ciclo iterato attraverso la lista collegata all'indice della tabella, se a metà nella tua iterazione, si verifica rehash. Potresti anche non riuscire a trovare la voce anche se esiste nella tabella hash.

+0

Sono d'accordo con te, ma non ne sono sicuro, quindi chiedi. – user1626860

14

Se la lettura non è stata sincronizzata, l'Hashtable potrebbe essere modificata durante l'esecuzione della lettura. Nuovi elementi potrebbero essere aggiunti, l'array sottostante potrebbe diventare troppo piccolo e potrebbe essere sostituito da uno più grande, ecc. Senza l'esecuzione sequenziale, è difficile gestire queste situazioni.

Tuttavia, anche se get non si arresta in modo anomalo quando l'Hashtable viene modificato da un altro thread, esiste un altro aspetto importante della parola chiave synchronized, ovvero la sincronizzazione della cache. Usiamo un esempio semplificato:

class Flag { 
    bool value; 

    bool get() { return value; } // WARNING: not synchronized 
    synchronized void set(bool value) { this->value = value; } 
} 

set è sincronizzato, ma get non è. Cosa succede se due thread A e B contemporaneamente leggono e scrivono in questa classe?

1. A calls read 
2.     B calls set 
3. A calls read 

È garantito al passaggio 3 che A veda la modifica del thread B?

No, non lo è, poiché A potrebbe essere in esecuzione su un core differente, che utilizza una cache separata in cui il vecchio valore è ancora presente. Pertanto, dobbiamo forzare B a comunicare la memoria ad un altro core e forzare A a recuperare i nuovi dati.

Come possiamo farlo rispettare? Ogni volta che un thread entra e lascia un blocco sincronizzato, viene eseguito un implicito memory barrier. Una barriera di memoria impone l'aggiornamento della cache. Tuttavia, è necessario che sia lo scrittore che il lettore debbano eseguire la barriera di memoria. Altrimenti, le informazioni non sono correttamente comunicate.

Nel nostro esempio, il thread B utilizza già il metodo sincronizzato set, quindi la sua modifica dei dati viene comunicata alla fine del metodo. Tuttavia, A non vede i dati modificati.La soluzione è rendere sincronizzato get, quindi è costretto a ottenere i dati aggiornati.

+0

Buona risposta. Grazie! – user1626860

Problemi correlati