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&nbsp;y no un regularHashMap? Toda modificación del mapa se realiza dentro delsynchronized&nbsp;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&nbsp;como estoy preguntando sobre elconcepto&nbsp;y no el uso de API :) a menos que el uso de esta API contribuya aHashMap&nbsp;vsConcurrentHashMap&nbsp;tema.

Actualizar 30/12/2016

Esta pregunta fue respondida por un comentario a continuación de Holger "HashMap.get&nbsp;no modifica la estructura, pero su invocación deput&nbsp;hace. Como hay una invocación deget&nbsp;fuera del bloque sincronizado, puede ver un estado incompleto de unput&nbsp;operación que ocurre simultáneamente. "¡Gracias!