Почему мы используем синхронизированную коллекцию, если она не гарантирует синхронизированный доступ на итераторах? - PullRequest
0 голосов
/ 29 января 2019

Например, в приведенном ниже коде мы должны заключить список в синхронизированный блок при выполнении итерации.Делает ли Collections.synchronizedList список синхронизированным?Почему мы делаем это, если это не обеспечивает никакого удобства?Спасибо!

List<Integer> list = Collections.synchronizedList( new ArrayList<>(Arrays.asList(4,3,52)));

synchronized(list) { 
      for(int data: list)
         System.out.print(data+" "); 
}

Ответы [ 4 ]

0 голосов
/ 29 января 2019

Collections.synchronizedList метод синхронизирует такие методы, как add, remove.Тем не менее, он не синхронизирует iterator() метод.Рассмотрим следующий сценарий:

  • Поток 1 выполняет итерации по списку
  • Поток 2 добавляет в него элемент

В этом случае вы будетеget ConcurrentModificationException и, следовательно, необходимо синхронизировать вызовы метода iterator().

0 голосов
/ 29 января 2019

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

JavaDoc упоминает, что итерация не синхронизирована и вам нужно синхронизировать ее самостоятельно.

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

Но другие операции доступаявляются потокобезопасными и также устанавливают , что происходит до отношения (так как они используют synchronized).

0 голосов
/ 29 января 2019

Почему мы делаем это, если это не обеспечивает никакого удобства

То, что это не поможет вам, когда итерация не то же самое, что и отсутствие удобства.* Все методы - get, size, set, isEmpty и т. Д. - синхронизированы.Это означает, что они видят все записи, сделанные в любом потоке.

Без синхронизации нет гарантии, что обновления, сделанные в одном потоке, будут видимы для любых других потоков, поэтому один поток может видеть размер 5например, другой видит размер 6.

Механизм для синхронизации списка состоит в том, чтобы все его методы synchronized: это фактически означает, что тело метода заключено в synchronized (this) { ... } block.

Это все еще верно для метода iterator(): это тоже synchronized.Но блок synchronized заканчивается, когда возвращается iterator(), а не когда вы заканчиваете итерацию.Это фундаментальное ограничение способа разработки языка.

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

0 голосов
/ 29 января 2019

См. https://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html

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

Также см. https://www.baeldung.com/java-synchronized-collections

...