web-dev-qa-db-ja.com

Javaのフェイルセーフおよびフェイルファーストイテレーターとは

Javaには、フェイルセーフとフェイルファストの2種類の反復子があります。

これはどういう意味ですか、それらの違いは何ですか?

95
Prateek

それらの違いは何ですか...

「フェイルセーフ」とは、失敗しないことを意味します。厳密に言えば、Javaにはフェイルセーフイテレーターとしてそのようなものはありません。正しい用語は「弱一貫性」です。 javadocによると:

「ほとんどの同時コレクション実装(ほとんどのキューを含む)も、通常のJava.util規則とは異なります。その反復子と分割子は、高速障害トラバーサルではなく弱一貫性を提供します。」

通常、弱い一貫性とは、コレクションが反復と同時に変更された場合、反復で確認されるものの保証が弱くなることを意味します。 (詳細は、各並行コレクションクラスjavadocsで指定されます。)

「高速で失敗する」とは:it may fail ...そして、障害状態が積極的にチェックされ、障害状態が(可能な場合)1)検出済みbeforeダメージを与えることができます。 Javaでは、ConcurrentModificationExceptionをスローすることにより、フェイルファーストイテレーターが失敗します。

「フェイルファースト」と「弱一貫性」の代替手段は、反復が予期せず失敗するセマンティックです。例えば間違った答えをしたり、予期しない例外をスローすることがあります。 (これは、Javaの初期バージョンのEnumeration AP​​Iの標準実装の動作でした。)

...また、コレクションに使用するイテレータとは異なります。

いいえ。これらは、標準のコレクションタイプによって実装されるイテレータのpropertiesです。つまり、同期とJavaメモリモデルに関して正しく使用すると、「フェイルファースト」または「弱一貫性」のいずれかです。1


フェイルファーストイテレーターは、コレクションオブジェクトでvolatileカウンターを使用して通常実装されます。

  • コレクションが更新されると、カウンターが増分されます。
  • Iteratorが作成されると、カウンターの現在の値がIteratorオブジェクトに埋め込まれます。
  • Iterator操作が実行されると、メソッドは2つのカウンター値を比較し、値が異なる場合はCMEをスローします。

フェイルセーフイテレータの実装は通常、軽量です。通常、特定のリスト実装のデータ構造のプロパティに依存します。一般的なパターンはありません。 (興味のある特定のコレクションクラスのソースコードを読んでください。)


1-ライダーは、フェイルファースト動作では、アプリケーションが同期とメモリモデルに関して正しくidすることを前提としています。つまり、(たとえば)適切な同期なしでArrayListを反復すると、リストの結果が破損する可能性があります。 「高速フェイル」メカニズムはおそらく同時変更を検出します(保証はされませんが)が、根本的な破損は検出しません。例として、 javadoc for Vector.iterator()はこう言います:

「イテレータのフェイルファースト動作は、一般的に言えば、非同期の同時変更が存在する場合にハード保証を行うことができないため、保証できません。フェイルファストイテレータは、ベストエフォートベースでConcurrentModificationExceptionをスローします。したがって、この例外に正確性を依存するプログラムを作成するのは誤りです。反復子のフェイルファースト動作は、バグを検出するためにのみ使用する必要があります。

80
Stephen C

むしろfail-fastおよびweakly-consistentタイプです:

反復中にコレクションのメソッド(コレクションの追加/削除)によってコレクションが変更された場合、Java.utilパッケージのイテレーターはConcurrentModificationExceptionをスローします

Java.util.concurrentパッケージのイテレータは通常、スナップショットを反復処理し、同時変更を許可しますが、イテレータが作成された後のコレクションの更新を反映しない場合があります。

40

唯一の違いは、フェイルセーフイテレータとは異なり、フェイルセーフイテレータは例外をスローしないことです。

1つのスレッドがコレクションを繰り返し処理している間にコレクションが構造的に変更された場合。これは、元のコレクションではなくコレクションのクローンで動作するためです。そのため、フェイルセーフイテレーターと呼ばれています。

CopyOnWriteArrayListのイテレータはフェイルセーフイテレータの例であり、ConcurrentHashMap keySetによって記述されたイテレータもフェイルセーフイテレータであり、JavaでConcurrentModificationExceptionをスローすることはありません。

22
Juned Ahsan