Как происходит сбой HashMap.computeIfAbsent при многопоточном использовании? - PullRequest
0 голосов
/ 05 февраля 2019

В документации по java.util.HashMap четко сказано: «Если несколько потоков одновременно обращаются к хэш-карте, и хотя бы один из потоков изменяет карту структурно, она должна быть синхронизирована извне».

Однакорассмотрим вариант использования, в котором вы используете карту в качестве кэша для сокращения создания неизменяемых объектов, когда в HashMap вызывается только computeIfAbsent (без удаления / удаления).И единственное, что вас волнует, - это то, что computeIfAbsent возвращает действительный объект;вам все равно, если computeIfAbsent иногда создает дополнительные объекты или перезаписывает существующую запись.

Что может случиться хуже всего?В моем случайном тестировании нет никаких негативных последствий.(Я бы использовал ConcurrentHashMap, но в этом случае он относительно медленный.)

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Что может случиться наихудшее?

Как насчет, поток A находится в вызове computeIfAbsent (k1, ...), в то время как поток B одновременно находится в get (k2)и get (k2) возвращает неправильное значение?

Я не знаю, может ли это быть худшее , которое может произойти, но это определенно то, что может произойти.

0 голосов
/ 05 февраля 2019

Проблема здесь: если вообще, то безопасность потока была бы реализацией детализацией.Может случиться, что это сработает для одной версии JVM, но будет немного отличаться или «выключено» в другой версии java.util.HashMap.

Цитирование другой ответа :

При этом наиболее часто используемые реализации Map, в частности HashMap, не являются поточно-ориентированными.Добавление элементов из разных потоков может оставить карту в несогласованном состоянии, когда, например, вставленные элементы не могут быть восстановлены, хотя size () показывает, что они присутствуют.

Другими словами: даже если выСегодня у меня нет проблем, просто переключение на другую версию Java теоретически может привести к провалу вашего дизайна.

Имейте в виду: единственная гарантия, которую вы имеете, - это интерфейс Map.Вы используете контейнер , который имеет некоторую внутреннюю структуру, которая обновляется несколькими потоками.Если это случается с , а не , вызывает несоответствия, то это чистое совпадение .

Если чтение и запись в HashMap будут "просто работать" в многопоточных настройках, зачем вообще нужен ConcurrentHashMap?!

...