Javaのイテレータには、フェイルセーフとフェイルファストの2つのタイプがあります。
これはどういう意味ですか、それらの違いは何ですか?
Javaのイテレータには、フェイルセーフとフェイルファストの2つのタイプがあります。
これはどういう意味ですか、それらの違いは何ですか?
回答:
それらの違いは何ですか...
「フェイルセーフ」とは(エンジニアリングにおいて)、損傷がまったくないか最小限の方法で何かが故障したことを意味します。厳密に言えば、Javaにはフェイルセーフイテレータのようなものはありません。イテレーターが失敗した場合(通常の「失敗」の意味)、損傷が発生することが予想されます。
あなたが実際に「弱一貫性」のイテレータを意味しているのではないかと思います。javadocは言う:
「ほとんどの並行コレクション実装(ほとんどのキューを含む)も、通常のjava.utilの規則とは異なります。それらのイテレーターとスプリッターは、高速失敗トラバーサルではなく、弱整合性を提供します。」
通常、弱い整合性とは、コレクションが反復と同時に変更された場合、反復で表示されるものの保証が弱いことを意味します。(詳細は、各並行コレクションクラスjavadocsで指定されます。)
「フェイルファスト」(システム設計で)は、故障状態を積極的にチェックして、(可能な場合は1)過度の損傷を与える前に故障状態を検出することを意味します。Javaでは、Fail-Fastイテレータはをスローすることで失敗しますConcurrentModificationException
。
「フェイルファスト」および「弱一貫性」の代替手段は、反復が予期せず失敗するセマンティックです。たとえば、時々間違った答えを出したり、予期しない例外をスローしたりします。(これは、Enumeration
Javaの初期バージョンでのAPIの一部の標準実装の動作でした。)
...そして、それらはコレクションに使用するイテレータとは異なります。
いいえ。これらは、標準のコレクション型によって実装されるイテレータのプロパティです。つまり、同期とJavaメモリモデルに関して正しく使用すると、「フェイルファースト」または「弱整合性」になります1。
フェイルファストイテレータは通常volatile
、コレクションオブジェクトのカウンタを使用して実装されます。
Iterator
作成され、カウンタの現在の値が中に埋め込まれているIterator
オブジェクト。Iterator
操作が行われ、方法は、2つのカウンタ値を比較し、両者が異なる場合CMEをスロー。対照的に、弱整合性のイテレータは通常、軽量であり、各並行コレクションの内部データ構造のプロパティを活用します。一般的なパターンはありません。興味があれば、さまざまなコレクションクラスのソースコードを読んでください。
1-ライダーは、フェイルファストの動作が、同期とメモリモデルに関してアプリケーションIDを正しく想定していることを示しています。つまり、(たとえば)ArrayList
を適切に同期せずに反復すると、リストの結果が破損する可能性があります。「ファストフェイル」メカニズムはおそらく同時変更を検出しますが(これは保証されていません)、根本的な破損は検出しません。例として、Javadoc for Vector.iterator()
は次のように言っています。
「イテレータのフェイルファスト動作は、非同期の同時変更が存在する場合、一般的には難しい保証ができないため保証できません。フェイルファストイテレータ
ConcurrentModificationException
はベストエフォートベースでスローします。したがって、この例外に正確性を依存するプログラムを書くのは間違っています。イテレータのフェイルファスト動作は、バグを検出するためだけに使用する必要があります。」
setArray
。
それらはむしろフェイルファストで弱く一貫したタイプです:
反復中にコレクションのメソッド(追加/削除)によってコレクションが変更された場合、java.util
パッケージのイテレータがスローConcurrentModificationException
します
java.util.concurrent
パッケージのイテレータは通常、スナップショットを反復処理し、同時変更を許可しますが、イテレータの作成後のコレクションの更新を反映しない場合があります。
Iterator
またはEnumeration
動作をフェイルファストまたはフェイルセーフとして指定しない。これは、特定の実装(すなわち、特定のコレクションですiterator()
/ elements()
動作を指定するなど、これらのオブジェクトを返すメソッド)。2)典型的な列挙の実装は、フェイルファストでもフェイルセーフでもありません。
唯一の違いは、フェイルセーフイテレータは、フェイルファストイテレータとは異なり、例外をスローしません。
1つのスレッドがコレクションを反復処理している間にコレクションが構造的に変更された場合。これは、元のコレクションではなくコレクションのクローンで作業するためであり、フェイルセーフイテレータと呼ばれるのはそのためです。
CopyOnWriteArrayListのイテレーターは、フェイルセーフイテレーターの例です。また、ConcurrentHashMapによって作成されたイテレーターkeySetもフェイルセーフイテレーターであり、JavaでConcurrentModificationExceptionをスローすることはありません。
このシナリオは「並行処理」に関連しており、同じリソースにアクセスする複数のユーザーを意味します。このような状況では、ユーザーの1人がそのリソースを変更しようとすると、 'ConcurrentProcessingException'が発生します。その場合、他のユーザーが不適切なデータを取得するためです。このタイプはどちらも、このような状況に関連しています。
簡単に言えば、
フェイルファースト:
フェイルセーフ :