Безопасен ли поток итератора EnumSet только для чтения?

У меня есть EnumSet, который является окончательным и неизменным, т.е. инициализируется один раз в конструкторе.

Безопасен ли метод contains() в этом потоке EnumSet? Он внутренне использует итератор для проверки содержимого. Следовательно, если два потока одновременно вызывают contains(), может ли позиция итератора в одном вызове повлиять на другой? Или итераторы имеют разные экземпляры в этих двух вызовах потоков?


person Harish    schedule 16.10.2014    source источник


Ответы (2)


Содержимое элемента EnumSet может быть изменено, несмотря на то, что ссылка на него является окончательной. Нет EnumSet неизменяемым. Однако вы можете обернуть свой EnumSet через Collections.unmodifiableSet(). Если вы также избегаете сохранения каких-либо ссылок на исходный EnumSet, тогда неизменяемый объект-оболочка функционально неизменен.

Несмотря на изменчивость, два итератора, работающие с одним и тем же Set в одно и то же время, не представляют проблемы, пока Set не изменяется. На самом деле это ничем не отличается от случая с одним итератором.

В любом случае метод contains() объекта EnumSet скорее всего не создает и не использует итератор. Класс реализует членство через битовый вектор, поэтому он использует битовые операции для выполнения теста contains().

person John Bollinger    schedule 16.10.2014

Нет, если два потока вызывают contains() одновременно, это вызовет iterator() дважды, что создаст два отдельных итератора.

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

Обратите внимание, что если вы изменяете набор в одном потоке, перебирая его (например, через contains) в другом, то в игру вступает этот фрагмент документации:

Возвращенный итератор является слабо непротиворечивым: он никогда не вызовет исключение ConcurrentModificationException и может отображать или не отображать эффекты любых модификаций набора, происходящих во время выполнения итерации.

person Jon Skeet    schedule 16.10.2014