Синхронизация доступа к ArrayList

Здравствуйте. Такой вопрос:

  1. В javadoc написано, что для thread-safe доступа к ArrayListу его нужно декорировать через Collections.synchronizeList. Я так понял, что этот метод просто возвращает list методы которого synchronized, это так?

  2. Из того же javadoc:

    List list = Collections.synchronizedList(new ArrayList());
    synchronized(list) {
      Iterator i = list.iterator(); // Must be in synchronized block
      while (i.hasNext())
        foo(i.next());
    }

It is imperative that the user manually synchronize on the returned list when iterating over it: ...

Зачем в этом случае вручную синхронизировать через synchronized(list)? Или это нужно делать, только когда работаешь с итераторами, и не обязательно, если обращаешься к листу через get(), add(), set()? Спасибо.

1 ответ

  1. Ну так посмотрите, что делает Collections.synchronizedList.. в IDE контрол-клик и читайте, что написано. Но вообще, вы обнаружите, что да, там каждый метод synchronized.
  2. Соответственно, этот факт и является причиной того, что есть необходимость синхронизоваться отдельно. Всё дело в том, что итератор сломается, если кто-то выполнит модификауцию списка между вызовами next(). Чтобы этого избежать и приходится делать более крупный блок synchronized.
  3. И да, нарушение внутреннего состояния списка внутри методов set никто не отменял: одновременный вызов метода set из разных поток с высокой вероятностью разрушит список. Поэтому, надо делать synchronizedList. Ну или можно просто руками везде синхронизовать, а не оборачивать. Лично я обычно так и делаю и редко пользуюсь этим декоратором. Он обычно полезен, если вы отдаёте список куда-то наружу, чего я стараюсь всеми правдами и неправдами избежать.

licensed under cc by-sa 3.0 with attribution.