Использование для каждого синтаксиса с Collections.synchronizedSet - PullRequest
4 голосов
/ 15 февраля 2010

Проблема заключается в следующем.Я сделал набор

Set<User> users = Collections.synchronizedSet(new HashSet<User>())
...
for(User u : users){
   //do something with u
} 

Теперь, в соответствии с документацией Java.

Обязательно, чтобы пользователь вручную синхронизировал возвращенный отсортированный набор при итерации по нему или любому изего представления subSet, headSet или tailSet.

 SortedSet s = Collections.synchronizedSortedSet(new HashSortedSet());
 ...
 synchronized(s) {
    Iterator i = s.iterator(); // Must be in the synchronized block
    while (i.hasNext())
       foo(i.next());
 }

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

Еще одна вещь, моя IDE (IntelliJ IDEA) постоянно сообщает, что использование синхронизированного блока над полем, которое не является окончательным, вряд ли будет иметь полезную семантику, поскольку разные потоки могут быть разными объектами, даже при работе стот же объект.

Ответы [ 3 ]

3 голосов
/ 15 февраля 2010
  1. должен ли я обернуть каждый цикл for ... Нет, вам не нужно оборачивать каждый цикл for синхронизированным блоком, фактически вы не должны этого делатьпотому что это идет с ухудшением производительности.Вам нужно обернуть только те циклы, которые выполняют итерации по коллекциям, к которым могут одновременно обращаться несколько потоков.

  2. моя IDE (IntelliJ IDEA) продолжает создавать отчеты .... В вашем конкретном случае это не проблема, потому что если разные потоки имеют разные экземпляры s, то, очевидно, итераторы тоже будут разными.

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

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

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

http://java.sun.com/docs/books/tutorial/collections/implementations/wrapper.html

Чтобы узнать больше о «последней переменной в синхронизированном блоке», взгляните на это: Конечная переменная и синхронизированный блок в java

1 голос
/ 15 февраля 2010

Поскольку для каждого используется Итератор под прикрытием, вы все равно получаете ConcurrentModificationException во время обработки для каждого, если ваш Set структурно модифицирован.

Что касается предупреждения, которое выдает ваша IDE, если вы переназначаете s, есть вероятность, что разные потоки видят разные объекты при попытке синхронизации на s. Использование volatile должно помочь здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...