Исключение параллельной модификации итератора - PullRequest
2 голосов
/ 12 февраля 2010

Этот код вызовет исключение одновременной модификации, если список был изменен в doSomething (). Можно ли избежать этого, заключив код в какой-то синхронизированный блок?

List l = Collections.synchronizedList(new ArrayList());

// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
  doSomething(i.next());
}

Ответы [ 6 ]

7 голосов
/ 12 февраля 2010
  • если вы удаляете элемент из списка, вы можете сделать это, позвонив по номеру iterator.remove() вместо list.remove(iterator.next())

  • если вы добавляете элемент - хорошо, создайте копию повторного списка и добавьте ее туда

  • если приведенный выше фрагмент кода является частью того же метода, то вам не нужен синхронизированный список или синхронизированные блоки - никакой другой поток не может получить доступ к локальному списку.

3 голосов
/ 12 февраля 2010

Вы можете изменить Collection, перебирая его, если вы делаете это через интерфейс Iterator. Вы можете использовать Iterator.remove() для удаления элементов.

0 голосов
/ 25 октября 2013
List l = Collections.synchronizedList(new ArrayList());

synchronized(l) { 
   // normal iteration -- can throw ConcurrentModificationException
   // may require external synchronization
   for (Iterator i=list.iterator(); i.hasNext(); ) {
      doSomething(i.next());
   }
}
0 голосов
/ 12 февраля 2010

Используйте CopyOnWriteArrayList вместо синхронизированного списка массивов

0 голосов
/ 12 февраля 2010

Я согласен с другими по поводу Iterator и remove().


Что касается синхронизации, я хотел бы добавить, что синхронизация предназначена для управления взаимодействиями между различными потоками .

Для объекта характерно синхронизировать несколько методов, и один из них будет вызывать другой. Поэтому разработчики языка решили, что один и тот же поток не будет заблокирован им самим при синхронизации.

Кроме того, думая об этом, если нить заблокирована, ожидая себя, у вас есть великолепная голодная перспектива! ; -)

Так что это отвечает на один из ваших вопросов: невозможно избежать проблемы, синхронизируя ваш код.

0 голосов
/ 12 февраля 2010

Вы не можете изменить его, пока вы итерируете его. Синхронизация здесь не поможет.

РЕДАКТИРОВАТЬ: я забыл, что итератор имеет метод remove. Так что можно убрать.

...