Как стать автором
Обновить

Комментарии 7

Подвох №1 несправедлив для ConcurrentHashMap, т.к. (из документации) «the function is applied at most once per key»

Ничего, зато в примере в конце статьи может вызваться несколько раз из разных тредов – похоже, автор лок забыл.

Более того в предложенной альтернативе все также тяжёлая функция может быть вызвана дважды

"условие ожидания — Condition await()/signal(). С synchronized это недоступно. " - а как же wait и notify?

В последнем примере, пока один поток будет висеть в выполнении calculateExpensive(key), ничего не мешает другим потокам тоже получить null в get и тоже упасть в вычисление. Тогда уже лучше использовать computeIfAbsent, который гарантирует только один вызов на ключ, судя по документации, а то, что кто-то в лямбду добавляет side-effectы, это уже проблема не ConcurrentHashMap, а разработчика. Да и не вижу в чем проблема долгих исчислений, это не блокирует всю таблицу, проблема лишь в том, что поток занят и наверное нужно вообще переосмысливать идею пользоваться лишь одной таблицой для приложений с высокой нагрузкой.

Всю таблицу конечно не блокирует, но корзину блокирует.

(из документации) Some attempted update operations on this map by other threads may be blocked while computation is in progress.

И при высокой конкурентности обновлений могут быть взаимные блокировки на разных ключах, что особо чувствительно при «прогреве» кешей, основанных на ConcurrentHashMap. (

А те примеры конечно да, из серии вредных советов.

А вот и настоящий вопрос для собеседования:

public synchronized int getCount() {
  return count;
}

Чем такая сигнатура отличается от public int getCount() с точки зрения вызывающего кода?

И это, computeIfAbsent блокирует чтение. Так что вся третья часть — булшит.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий