Bloqueio duplo verificado com ConcurrentMap

Tenho um pedaço de código que pode ser executado por vários encadeamentos que precisam executar uma operação vinculada a E / S para inicializar um recurso compartilhado armazenado em umConcurrentMap. Preciso tornar esse segmento de código seguro e evitar chamadas desnecessárias para inicializar o recurso compartilhado. Aqui está o código do buggy:

    private ConcurrentMap<String, Resource> map;

    // .....

    String key = "somekey";
    Resource resource;
    if (map.containsKey(key)) {
        resource = map.get(key);
    } else {
        resource = getResource(key); // I/O-bound, expensive operation
        map.put(key, resource);
    }

Com o código acima, vários threads podem verificar oConcurrentMap e veja se o recurso não existe e todas as tentativas de chamargetResource() que é caro. Para garantir apenas uma única inicialização do recurso compartilhado e tornar o código eficiente depois que o recurso foi inicializado, desejo fazer algo assim:

    String key = "somekey";
    Resource resource;
    if (!map.containsKey(key)) {
        synchronized (map) {
            if (!map.containsKey(key)) {
                resource = getResource(key);
                map.put(key, resource);
            }
        }
    }

Esta é uma versão segura do bloqueio com verificação dupla? Parece-me que, uma vez que os cheques são chamadosConcurrentMap, ele se comporta como um recurso compartilhado declarado comovolatile e, assim, evita qualquer um dos problemas de "inicialização parcial" que possam ocorre

questionAnswers(6)

yourAnswerToTheQuestion