2012-04-27 11 views
12

Tengo una clase de caché que contiene un volatile HashMap<T> para almacenar elementos de caché.Volatile HashMap vs ConcurrentHashMap

Tengo curiosidad de cuáles serían las consecuencias de cambiar volatile HashMap a ConcurrentHashMap?

¿Aumentaré mi rendimiento? Este caché es de solo lectura.

¿Cuál sería la mejor opción para usar? solo HashMap? La memoria caché se está rellenando en un intervalo.

+3

Si es de solo lectura no necesita ... tampoco. –

+4

'volátil' en un' HashMap' significa que atraviesa una barrera de memoria cuando obtiene/configura el objeto 'HashMap'. No hace nada cuando agrega o elimina elementos del mapa – Gray

+0

@BrianRoach ¿qué usaría? – DarthVader

Respuesta

31

En primer lugar, parece que no entiende lo que hace la palabra clave volatile. Se asegura de que si el valor de referencia mantenido por la variable declarada volatile cambia, otros subprocesos lo verán en lugar de tener una copia en caché. No tiene nada que ver con la seguridad del hilo con respecto al acceso al HashMap

Dado que, y el hecho de que diga el HashMap es de solo lectura ... no necesita utilizar nada que proporcione hilo. de seguridad que incluye una edición ConcurrentHashMap

añadir: su última edición que ahora dicen "La memoria caché se está llenando en un intervalo de"

eso no es de sólo lectura entonces, ¿verdad?

Si usted va a tener roscas lee de éste mientras se está escribiendo (la actualización del HashMap existente), entonces debería usar un ConcurrentHashMap, sí.

Si está completando una nueva HashMap luego asignar a la variable existente, a continuación, utiliza volatile

+0

bueno, esa fue la razón por la que estaba usando volátil, había una lectura de hilo de fondo desde el archivo y creaba un nuevo hashmap luego asignando al caché. Estoy planeando cambiar el diseño, es por eso que pregunté. Usted respondió ambos casos sin embargo. Gracias. – DarthVader

+0

Bueno, en realidad puede usar 'volátil' para asegurarse de que las personas vean los elementos más actuales (básicamente de la misma manera que lo hace para obtener elementos de matriz" volátiles "), es simplemente a) mal rendimiento, b) intrincado, c) no ayuda con las condiciones internas de carrera cuando se agregan datos yd) simple estupidez. Pero factible! ;) – Voo

+0

@Voo ¿qué usarías? ¿o cómo lo harías? – DarthVader

6

Usted dice que el caché se, sino que también van a actualizar en un intervalo que parece contradictorio de sólo lectura.

Si todo el caché se actualiza en un intervalo, seguiría usando el volátil. El elemento volátil se asegurará de que el mapa actualizado se publique de forma segura.

public final class Cache 
{ 
    private volatile Map<?,?> cache; 

    private void mapUpdate() { 
     Map<?,?> newCache = new HashMap<>(); 

     // populate the map 

     // update the reference with an immutable collection 
     cache = Collections.unmodifiableMap(newCache); 
    } 
} 

Si el intervalo de actualización es la modificación de la misma caché, entonces es probable que desee utilizar un ConcurrentHashMap, o copiar el mapa, actualizar la copia, y actualizar la referencia.

public final class Cache 
{ 
    private volatile Map<?,?> cache; 

    private void mapUpdate() { 
     Map<?,?> newCache = new HashMap<>(cache); 

     // update the map 

     // update the reference with an immutable collection 
     cache = Collections.unmodifiableMap(newCache); 
    } 
} 
+0

Consideraría mantener el campo de caché no volátil. Debido a Collections.unmodifiableMap, el enlace de campo final a la nueva versión del mapa se publicará con seguridad. En algún momento, todos los hilos recogerían una nueva versión del mapa de caché. Por lo general (¡pero no siempre!) No importa si la memoria caché estará disponible no inmediatamente sino en un par de milisegundos. Y al hacer que este campo sea no volátil mejora un poco el rendimiento de la memoria caché de la CPU. – vlsergey