Двойная проверка блокировки с обычным HashMap
Вернуться к параллелизму. К настоящему времени ясно, что дляdouble checked locking
для работы переменная должна быть объявлена какvolatile
, Но что делать, если двойная проверка блокировки используется, как показано ниже.
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;
}
}
Почему это действительно должно бытьConcurrentHashMap и не обычныйHashMap? Все изменения карты выполняются в пределахsynchronized
блок и код не использует итераторы, так что технически не должно быть проблем "одновременного изменения".
Пожалуйста, избегайте использованияputIfAbsent
/computeIfAbsent
как я спрашиваю оконцепция а не использование API :), если использование этого API не способствуетHashMap
противConcurrentHashMap
предмет.
Обновление 2016-12-30
На этот вопрос ответил комментарий ниже от Holger "HashMap.get
не изменяет структуру, но ваш вызовput
делает. Так как есть вызовget
вне синхронизированного блока, он может видеть неполное состояниеput
операция происходит одновременно. "Спасибо!