Является ли List.iterator () потокобезопасным?

#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 причине.

лучшее описание здесь