Doble comprobación de bloqueo con HashMap normal
De vuelta a la concurrencia. Por ahora está claro que para eldouble checked locking
para trabajar la variable necesita ser declarada comovolatile
. Pero entonces, ¿qué pasa si el bloqueo de doble verificación se usa como a continuación?
class Test<A, B> {
private final Map<A, B> map = new HashMap<>();
public B fetch(A key, Function<A, B> loader) {
B value = map.get(key);
if (value == null) {
synchronized (this) {
value = map.get(key);
if (value == null) {
value = loader.apply(key);
map.put(key, value);
}
}
}
return value;
}
}
¿Por qué realmente tiene que ser unConcurrentHashMap y no un regularHashMap? Toda modificación del mapa se realiza dentro delsynchronized
bloquear y el código no utiliza iteradores, por lo que técnicamente no debería haber problemas de "modificación concurrente".
Evite sugerir el uso deputIfAbsent
/computeIfAbsent
como estoy preguntando sobre elconcepto y no el uso de API :) a menos que el uso de esta API contribuya aHashMap
vsConcurrentHashMap
tema.
Actualizar 30/12/2016
Esta pregunta fue respondida por un comentario a continuación de Holger "HashMap.get
no modifica la estructura, pero su invocación deput
hace. Como hay una invocación deget
fuera del bloque sincronizado, puede ver un estado incompleto de unput
operación que ocurre simultáneamente. "¡Gracias!