Perché concurententhashmap.putifabsent è sicuro?
-
13-11-2019 - |
Domanda
Ho letto per la concorrenza da ieri e non conosco molte cose ... Comunque alcune cose stanno iniziando a chiarire ...
Capisco perché il doppio controllo del blocco non è sicuro (mi chiedo quale sia la propatà che la condizione rara verificarsi) ma volatile risolve il problema in 1,5 + ....
Ma mi chiedo se questo si verifica con putifAbsent
Come ...
myObj = new myObject("CodeMonkey");
cHashM.putIfAbsent("keyy",myObj);
.
Quindi questo assicura che myObj
sarebbe stato indiano al 100% quando un altro thread fa un cHashM.get()
???Poiché potrebbe avere un riferimento ISNT completamente inizializzato (il problema del blocco a doppio controllo)
Soluzione
Se si invoca concurrentHashMap.get(key)
e restituisce un oggetto, tale oggetto è garantito per essere completamente inizializzato.Ogni inserimento (o putifabsent) otterrà un blocco specifico del secchio e aggiungerà l'elemento alle voci del secchio.
Ora puoi passare attraverso il codice e notare che il metodo Get non ottiene questo stesso blocco.Quindi puoi discutere che ci può essere una lettura obsoleta, non è nemmeno vera.La ragione qui è che il valore all'interno della voce stessa è volatile.Quindi sarai sicuro di ottenere la lettura più aggiornata.
Altri suggerimenti
Il metodo putIfAbsent
in ConcurrentHashMap
è il metodo check-IF-assente-quindi impostato.È un'operazione atomica.Ma per rispondere alla parte seguente: "Quindi questo assicura che MyOBJ sarebbe stato indiano al 100% quando un altro thread fa un chashm.get ()", dipenderebbe da quando l'oggetto viene inserito nell'HashMap.Di solito c'è una precedenza successiva, I.e., Se il chiamante viene prima che l'oggetto venga posizionato nella mappa, allora null
verrà restituito, altrimenti il valore verrà restituito.
La parte rilevante della documentazione è questa:
.Effetti di consistenza della memoria: come con Altre collezioni simultanee, azioni in un thread prima di posizionare un oggetto in un concordrentmap come chiave o valore accadere, prima delle azioni successive a l'accesso o la rimozione di quell'oggetto dal concubito in un altro Discussione.
Allora, sì, hai il tuo è presente-prima relazione.
Non sono un esperto in questo, ma guardando l'implementazione di Segment
in ConcurrentHashMap
Vedo che il campo volatile
count
sembra essere utilizzato per garantire una corretta visibilità tra i fili.Tutte le operazioni di lettura devono leggere il campo count
e tutte le operazioni di scrittura devono scrivere ad esso.Dai commenti nella classe:
Read operations can thus proceed without locking, but rely on selected uses of volatiles to ensure that completed write operations performed by other threads are noticed. For most purposes, the "count" field, tracking the number of elements, serves as that volatile variable ensuring visibility. This is convenient because this field needs to be read in many read operations anyway: - All (unsynchronized) read operations must first read the "count" field, and should not look at table entries if it is 0. - All (synchronized) write operations should write to the "count" field after structurally changing any bin. The operations must not take any action that could even momentarily cause a concurrent read operation to see inconsistent data. This is made easier by the nature of the read operations in Map. For example, no operation can reveal that the table has grown but the threshold has not yet been updated, so there are no atomicity requirements for this with respect to reads..