#java #list #collections #iterator #thread-safety
#java #Список #Коллекции #итератор #потокобезопасность
Вопрос:
В Java: является List.iterator()
потокобезопасным, т. Е. отражает ли возвращаемый итератор текущее состояние списка в любое время или только состояние списка на момент его создания?
Ответ №1:
Поведение List.iterator() не определено и не согласуется с различными реализациями List.
Для ArrayList, LinkedList, вы можете получить исключение ConcurrentModificationException, если список изменяется при выполнении итерации по нему. (Это не гарантируется) Способ избежать этой проблемы — использовать synchronizedList() и заблокировать список во время итерации по нему.
Для Vector коллекция синхронизирована, но итератор не потокобезопасен.
Для CopyOnWriteArrayList вы получаете снимок элементов в списке во время вызова iterator(), этот итератор потокобезопасен, и вам не нужно использовать какую-либо блокировку. Примечание: содержимое элементов может изменяться.
Ответ №2:
Ни один итератор не является потокобезопасным. Если базовая коллекция изменяется во время итерации, создается ConcurrentModificationException
.
Даже итераторы синхронизированных коллекций не потокобезопасны — вам приходится синхронизировать вручную.
Одним из исключений является CopyOnWriteArrayList
, который сохраняет снимок во время итерации.
Комментарии:
1. «Ни один итератор не является потокобезопасным, кроме одного» можно было бы записать как «Все потокобезопасны, кроме двух или трех» 😉
2. Если базовая коллекция изменяется во время итерации другим потоком, CME может быть выброшен, а может и не быть выброшен, поскольку внутренний счетчик изменений не является атомарным.
Ответ №3:
Это зависит от того, какой класс вы используете,
не по Collections.synchronizedList(new ArrayList<>());
причине, но
по CopyOnWriteArrayList
причине.
лучшее описание здесь