Подтвердить что ты не робот

Что такое отказобезопасные и отказоустойчивые итераторы в Java

В Java существует два типа итераторов: отказоустойчивые и отказоустойчивые.

Что это значит, и есть ли разница между ними?

4b9b3361

Ответ 1

  В чем разница между ними...

"Отказоустойчивость" означает: он не подведет. Строго говоря, в Java нет такой вещи, как как отказоустойчивый итератор. Правильный термин "слабо последовательный". Javadoc говорит:

"Большинство одновременных реализаций Collection (включая большинство очередей) также отличаются от обычных соглашений java.util тем, что их итераторы и сплитераторы обеспечивают слабосогласованный, а не быстрый обход".

Как правило, слабая согласованность означает, что если коллекция изменяется одновременно с итерацией, гарантии того, что видит итерация, являются более слабыми. (Детали будут указываться в javadocs каждой параллельной коллекции классов.)

"Fail fast" означает: он может потерпеть неудачу... и условие отказа проверяется агрессивно, так что условие отказа (где это возможно 1) обнаруживается до того, как может быть нанесено повреждение. В Java отказоустойчивый итератор дает сбой, выдавая ConcurrentModificationException.

Альтернатива "отказоустойчивому" и "слабо согласованному" является семантической, когда итерация не может быть непредсказуемой; например иногда давать неправильный ответ или выдавать неожиданное исключение. (Это было поведение некоторых стандартных реализаций API Enumeration в ранних версиях Java.)

... и они отличаются от итератора, который мы используем для сбора.

Нет. Это свойства итераторов, реализованных стандартными типами Collection; то есть они либо "быстро проваливаются", либо "слабо согласованы"... при правильном использовании в отношении синхронизации и модели памяти Java 1.


Отказоустойчивые итераторы обычно реализуются с использованием счетчика volatile для объекта сбора.

  • Когда коллекция обновляется, счетчик увеличивается.
  • Когда создается Iterator, текущее значение счетчика внедряется в объект Iterator.
  • Когда выполняется операция Iterator, метод сравнивает два значения счетчика и выдает CME, если они различаются.

Реализация отказоустойчивых итераторов обычно легкоspring. Они обычно полагаются на свойства структур данных реализации конкретного списка. Там нет общей картины. (Прочитайте исходный код для конкретных классов коллекции, которые вас интересуют.)


1 - The rider is that fail-fast behavior assumes that the application id correctly with respect to synchronization and the memory model. That means that (for example) if you iterate an [TG46] without proper synchronization, the result could be a corrupted list result. The "fast fail" mechanism will probably detect the concurrent modification (though that isn't guaranteed), but it won't detect the underlying corruption. As an example, javadoc for [TG47] says this:

"The fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw [TG48] on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs."

Ответ 2

Они скорее fail-fast и слабо согласованные типы:

Итераторы из java.util package throw ConcurrentModificationException, если коллекция была изменена методами сбора (добавление/удаление) при повторении

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

Ответ 3

Единственное различие заключается в отказобезопасном итераторе, которое не выбрасывает исключение, в отличие от отказоустойчивого итератора.

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

Итератор CopyOnWriteArrayList является примером отказоустойчивого Iterator, итератор, написанный ConcurrentHashMap keySet, также является отказоустойчивым итератором и никогда не бросает ConcurrentModificationException в Java.