Bloqueio verificado duas vezes com HashMap regular

Voltar para simultaneidade. Até agora, está claro que, para odouble checked locking para trabalhar, a variável precisa ser declarada comovolatile. Mas e se o bloqueio com verificação dupla for usado como abaixo.

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 que realmente tem que ser umConcurrentHashMap e não um regularHashMap? Toda modificação do mapa é feita dentro dosynchronized block e o código não usa iteradores, portanto tecnicamente não deve haver problemas de "modificação simultânea".

Evite sugerir o uso deputIfAbsent/computeIfAbsent como eu estou perguntando sobre oconceito e não o uso da API :), a menos que o uso desta API contribua paraHashMap vsConcurrentHashMap sujeito.

Atualização 30/12/2016

Esta pergunta foi respondida por um comentário abaixo por Holger "HashMap.get não modifica a estrutura, mas sua chamada deput faz. Como existe uma invocação deget fora do bloco sincronizado, ele pode ver um estado incompleto de umput operação acontecendo simultaneamente. "Obrigado!

questionAnswers(1)

yourAnswerToTheQuestion