2016-09-22 6 views
1

WORST POSSIBLE結果が(データ破損以外の)Javaの複数のスレッドによって変更されたコレクションを同期しないことを知りたいですか?Javaコレクションの同期化の不一致

実際の例では、スレッドの数は10より大きくなり、コレクション(HashSet)は約100,000要素(さらに多分)に増加する可能性があります。

おかげでHashSetの以来

+0

あなたは破損していて信頼できないデータになります – TheLostMind

+1

'HashMap'に関しては、デッドループに終わることがあります。 – passion

+0

@ passionあなたはもう少し説明できますか?無限ループのようなものですか? – filip

答えて

2

は内部HashMapを使用して、あなただけのHashMapのputValメソッドの定義を調べて自分で見ることができます - そのメソッドの実行中の任意の時点で、別のスレッドが同じことをやって起動することがあります。たとえば、サイズ変更の途中でキャッチすることができます。つまり、データが古いテーブルに書き込まれるか、2つの新しいテーブルが同時に作成されます。

結果は常にデータ破損であり、そのような事態後は機能しない可能性があります。

1

スレッドの1つがセットを反復処理していて、別のスレッドがそのスレッドを変更している場合、ConcurrentModificationExceptionが返されることがあります。

詳細な説明はHashSetドキュメントにあります。この実装は同期化されていないことを

注意。複数のスレッドが同時にハッシュセットにアクセスし、スレッドの少なくとも1つがセットを変更する場合は、外部と同期する必要があります。これは、通常、セットを自然にカプセル化するオブジェクトで同期することによって行われます。そのようなオブジェクトが存在しない場合、Collections.synchronizedSetメソッドを使用してセットを「ラップする」必要があります。これは最高のセットへの偶発的な非同期アクセスを防ぐために、作成時に行われます。

Set s = Collections.synchronizedSet(new HashSet(...));

このクラスのiteratorメソッドによって返される反復子は、フェイルファストのとおりです。セットはイテレータの後に任意の時点で変更された場合イテレータ自身のremoveメソッド以外の方法で、IteratorがConcurrentModificationExceptionをスローします。したがって、同時の変更に直面して、イテレータは、未定義の時間に任意の非決定論的な動作を将来的に危険にさらすのではなく、迅速かつきれいに失敗します。

イテレータのフェイル・ファーストの動作は、一般的に言えば、非同期同時変更の存在下では何の保証もできないため、保証できません。フェイル・ファースト・イテレータはベスト・エフォート・ベースでConcurrentModificationExceptionをスローします。したがって、この例外に依存するプログラムを記述するのは間違いです。イテレータのフェイル・ファーストの動作は、バグの検出にのみ使用する必要があります。

1

最悪の場合は、データ構造がポイントに戻ります。 Java 7までのHashMapは無限ループに陥る可能性があります。つまり、スレッドが返されることはなく、エラーは発生しません。