3

Я попал в состояние live lock в параллельном hashmap #computeIfAbsent, когда функция, используемая для вычисления, вызывает #computeIfAbsent на той же карте.Live Lock в ConcurrentHashMap

Концептуально вызов вызов выглядеть так

final Map<String, Boolean> map = new ConcurrentHashMap<>(); 
map.computeIfAbsent("k1", k1 -> map.computeIfAbsent("k2", k2 -> Boolean.TRUE)); 

(с около 3 мс от центрального процессора сжигаемого между, вычисляемых). К сожалению, я не могу придумать хороший модульный тест для непрерывного воспроизведения проблемы.

Однако

есть еще один живой замок, который может дать некоторую подсказку присутствует, если функция вычисления пытается удалить ключ, на котором он вызывается:

final Map<String, Boolean> map = new ConcurrentHashMap<>(); 
map.computeIfAbsent("k", k -> map.remove("k")); 

в то время как второй пример довольно запутанный использование параллельной хэш-карты, это приводит к тому же stacktrace, что и первая прямая блокировка, поэтому может быть полезно.

Любая помощь будет высоко оценена!

+0

[Лучшая обработка ошибок] (http://stackoverflow.com/questions/28840047/recursive-concurrenthashmap-computeifabsent-call-never-terminates-bug-or-fea/28845674#28845674) находится в репозитории Дуга, но не но в выпуске JDK. –

ответ

4

Ну документация ConcurrentHashMap.computeIfAbsent прямо говорит:

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

Emphasis mine. Внутренне computeIfAbsent синхронизируется с записью хэш-таблицы, содержащей ваш ключ. У вас могут быть неожиданные блокировки при изменении другого ключа, который попадает в ту же запись, что и в настоящее время обрабатывается.

В общем, вы должны избегать таких модификаций. К сожалению, у вас недостаточно контекста для вашей проблемы, поэтому я не могу предложить альтернативное решение.

+0

Дох, я дважды читал javadoc и упускал функциональный контракт. Спасибо за внимание! –