ConcurrentHashMap с ArrayList в качестве значения

#java #concurrency #arraylist #hashmap

#java #параллелизм #arraylist #хэш-карта

Вопрос:

Мне нужно использовать хэш-карту формы <String, ArrayList<String>> , к которой будут обращаться несколько разных потоков. Из того, что мне удалось понять, ConcurrentHashMap является предпочтительным методом. Но будут ли какие-либо проблемы с тем фактом, что значение карты является ArrayList? Должен ли я определять значение как синхронизированный ArrayList или что-то в этом роде?

Ответ №1:

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

Поэтому используйте потокобезопасный список, если это верно.

Редактировать — теперь, когда я думаю об этом, кроличья нора заходит дальше. У вас есть ваша карта, у вас есть ваш список, и у вас есть объекты в списке. Все, что могут изменять несколько потоков, должно быть потокобезопасным. Итак, если многие потоки могут изменять карту, списки и объекты в списках, то все они должны иметь средства защиты от потоков. Если одновременно могут быть изменены только экземпляры Map и List, только они нуждаются в безопасности потоков. Если несколько потоков могут читать все, но не изменять, то вам не нужна никакая потокобезопасность (я думаю, кто-нибудь поправит меня, если это неправильно)

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

1. Я see…so как мне использовать потокобезопасный список? Я имею в виду, как мне инициализировать ConcurrentHashMap? Я не могу написать новую ConcurrentHashMap<Строка, коллекции. synchronizedList<Строка>>()…

2. Что ж, предполагая, что доступ к одному и тому же списку будет крайне редким, простая синхронизация по списку ПОСЛЕ того, как вы получите его из HashMap (synchronize(list) {}) должна работать просто отлично. В противном случае коллекции. synchronizedList() по-прежнему возвращает обычный список, поэтому вам не нужно изменять подпись хэш-карты — просто убедитесь, что на карту добавлены только синхронизированные списки.

3. @Moshe: Чтобы сделать комментарий Voo более понятным: используйте <String, List<String>> в качестве параметра типа вашей карты не <String, someSpecialListType<String>> . Затем вы можете поместить в любой список, который вы хотите — обычно вам не нужно знать, какая реализация.

Ответ №2:

ConcurrentHashMap гарантирует атомарность в своих изменяющихся методах, например, putIfAbsent, computeIfAbsent, computeIfPresent, поэтому, если все изменения будут выполнены с помощью этих методов, проблем не возникнет.

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