La sincronizzazione di modificatori ConcurrentHashMap
-
23-08-2019 - |
Domanda
Vorrei mettere in cache una certa IO con l'aiuto di ConcurrentHashMap
. La modifica del file binario deve essere riflessa nella cache pure. Poiché la cache sta per essere utilizzata da più thread tutte le operazioni di IO sono sincronizzate. Modifiche di carta vanno all'interno dello stesso blocco synchronized
. Che si presenta più o meno come:
synchronized (file) {
file.deleteRecord(index)
map.remove(index);
}
e
synchronized(file) {
file.writeRecord(index, record);
map.put(index, record);
}
Sia map
e file
sono private e non si vedono da fuori cache di classe.
è thread-sicurezza preservata se la cache legge, vale a dire map.get(index)
, andare senza il blocco synchronized
?
Come ho detto prima, ConcurrentHashMap
viene utilizzato come mappa implementazione.
Soluzione
Yup. Questo è fondamentalmente il punto di ConcurrentHashMap
. Da la documentazione :
operazioni di recupero (compreso get) generalmente non bloccare, così possono sovrapporsi con operazioni di aggiornamento (compresi put e rimuovere). Recuperi riflettono la risultati della più recente completato operazioni di aggiornamento della holding alla loro insorgenza.
Una raccolta simultanea è thread-safe, ma non governato da un serratura esclusione singolo. Nel particolare caso di
ConcurrentHashMap
, permette in modo sicuro qualsiasi numero di concomitante legge così come un sintonizzabile numero di scritture contemporanee.
(Sia di quelle pagine di documentazione hanno molto più dettagliato, naturalmente. Sono la pena di leggere con attenzione.)
Altri suggerimenti
Sì, filo di sicurezza è conservato fino ai riferimenti cartografici, grazie all'implementazione ConcurrentHashMap.
Gli oggetti archiviati nella mappa sono un'altra storia.
Sì, ConcurrentHashMap è thread-safe, in modo da leggere (o scrivere) non richiede alcun blocco da parte vostra.
Tuttavia, nel tuo esempio, si potrebbe finire con la seguente sequenza di eventi:
file.deleteRecord(index);
map.get(index) // returns the mapping for index even though it has been deleted from file
map.remove(index);
(lo stesso per writeRecord / put). Questo potrebbe o non potrebbe essere un problema nel tuo caso.
Bene, come tutti qui dice, questo è thread-safe in che avete un accade-prima di relazione tra la scrittura per la cache e la lettura dalla cache, ma che può essere privo di significato a seconda di ciò che altre garanzie che si spera per.
Per esempio, a meno che non fsync il file non c'è alcuna garanzia che il record sarà scritto su disco, quindi non si può leggere il record dal disco (a seconda del file system e un paio di altri fattori). Non c'è inoltre accade-prima rapporto tra il writeRecord / deleteRecord e carta di scrittura e di lettura dalla mappa, in modo che il JMM non garantisce che leggete qualcosa dalla mappa che è stata definitivamente scritta il file.
È possibile prendere una garanzia che lo stato delle index
e record
oggetti come scritto sarà quello che verrà letto, anche se uno di questi sono mutabili, allora questo può essere una garanzia abbastanza inutile.