Domanda

è

final Map<Integer,Map<String,Integer>> status = new ConcurrentHashMap<Integer, Map<String,Integer>>();
Map<Integer,Map<String,Integer>> statusInner = new ConcurrentHashMap<Integer, Map<String,Integer>>();
status.put(key,statusInner);

lo stesso

volatile Map<Integer,Map<String,Integer>> status = new ConcurrentHashMap<Integer,   Map<String,Integer>>();
Map<Integer,Map<String,Integer>> statusInner = new ConcurrentHashMap<Integer, Map<String,Integer>>();
status.put(key,statusInner);

nel caso in cui l'interno Map si accede da diversi thread?

o è qualcosa di ancora di simile richiesta:

volatile Map<Integer,Map<String,Integer>> status = new ConcurrentHashMap<Integer, Map<String,Integer>>();
volatile Map<Integer,Map<String,Integer>> statusInner = new ConcurrentHashMap<Integer, Map<String,Integer>>();
status.put(key,statusInner);

Nel caso in cui il NON è una "cascata" mappa, finale e volatile hanno, alla fine, lo stesso effetto di rendere shure che tutte le discussioni vedono sempre il corretto contenuto della mappa ... Ma cosa succede se la mappa contiene iteself una mappa, come nell'esempio ... come faccio a fare shure che l'interno map è correttamente "Memory barrierate"?

carri armati! Tom

È stato utile?

Soluzione

volatile riguarda solo la capacità di altri thread per leggere il valore delle variabili è attaccato. E 'in alcun modo influisce sulla capacità di un altro thread per vedere le chiavi ei valori della mappa. Per esempio, ho potuto avere un volatile int[]. Se cambio il riferimento-cioè. se cambio la matrice reale che punta a-altri thread di lettura della matrice sono garantiti per vedere che il cambiamento. Tuttavia, se cambio il terzo elemento dell'array tali garanzie sono fatti.

Se status è final, la costruzione della classe contenente crea un rapporto happens-before con ogni successiva legge, in modo che siano in grado di vedere il valore di status. Allo stesso modo qualsiasi legge per la variabile volatile sono garantiti per vedere l'assegnazione di riferimento più recenti ad esso. E 'a differenza che stai scambiando la mappa attuale intorno molto spesso, più come si sta solo cambiando le chiavi e soggiorni complessivi mappa degli oggetti come è.

Per questa domanda, allora, è necessario consultare la documentazione per ConcurrentHashMap:

operazioni di recupero (compreso get) generalmente non bloccare, così possono sovrapporsi con operazioni di aggiornamento (compresi put e rimuovere). Recuperi riflettono la risultati più recentemente completato operazioni di aggiornamento della holding alla loro insorgenza.

Questa è una specie di stranamente formulata, ma il succo è che qualsiasi operazione get il cui esordio è dopo il ritorno di qualche operazione put è garantito per vedere i risultati di tale put. Quindi non hai nemmeno bisogno di un volatile sulla mappa esterna; Disse il JLS:

Un filo che può vedere solo un riferimento a un oggetto dopo oggetto ha stato completamente inizializzati garantito per vedere il modo corretto valori inizializzato per quell'oggetto campi finali.

Sommario

Un final sulla mappa esterna è sufficiente.

Altri suggerimenti

vale la pena di guardare Google-Collezioni e, in particolare, MapMaker che consente in modo intelligente l'installazione e creare mappe. Essere in grado di impostazione valori deboli, per consentire una migliore raccolta dei rifiuti, e tempi di scadenza, in modo da poter utilizzare Maps per la memorizzazione nella cache efficace, è brillante. Come le mappe che MapMaker fa (: P). Hanno le stesse proprietà ConcurrentHashMap, si può essere felici con il suo filo di sicurezza

final mapMaker = new MapMaker().weakValues(); //for convenience, assign
final Map<Integer,Map<String,Integer>> status = mapMaker.makeMap();
status.put(key, mapMaker.<String, Integer>makeMap());

Si prega di nota, si potrebbe desiderare di guardare la definizione di statusInner, in quanto non mi sembra giusto.

Credo che la migliore risposta è che volatile non è un modo per garantire la thread-safety.

Utilizzando ConcurrentHashMap è più o meno tutto ciò che serve. Sì, fare il riferimento al Map final di livello superiore, se è possibile, ma volatile non è necessario, in ogni caso. Il riferimento di secondo livello Map all'interno sono l'attività di ConcurrentHashMap per ottenere il diritto, e uno si assume lo fa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top