#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, поэтому, если все изменения будут выполнены с помощью этих методов, проблем не возникнет.
Но в то же время несколько потоков могут считывать одну и ту же запись карты (одновременное чтение разрешено). поэтому несколько потоков могут получать доступ к небезопасной коллекции (значение карты) и изменять ее