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!