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!

Respuestas a la pregunta(1)

Su respuesta a la pregunta