2017-02-18 11 views
4

をマルチスレッドでは、私はこの方法containsはHashSetのオブジェクト上でスレッドセーフであるかどうかを知りたいHashSetのと

のJava 7で動作します。

HashSetは1つのスレッドで初期化されます。次に、変更不可能なコレクション(Collections.unmodifiableSet)でHashSetをラップします。初期化後、複数のスレッドはメソッドcontainsのみを呼び出します。

私がJavadocを読むと、私にとっては不明です。

HashSet Javadocで私達は、このクラスは、ハッシュテーブル(実際にはHashMapのインスタンス)をSetインタフェースを実装

を読むことができます。この実装は同期化されていないことを

...

注意。

そしてHashMap Javadocに、我々は読むことができます:この実装は同期化されていないことを

注意を。複数のスレッドが同時にハッシュマップにアクセスし、少なくとも1つのスレッドがマップを構造的に変更する場合は、外部と同期させる必要があります。 (構造的修飾は、一つ以上のマッピングを追加または削除する操作であり、単にインスタンスが既に含まれていることをキーに関連付けられている値を変更することは構造的修飾ではない。)

私にとって、この手段メソッドcontainsは構造的な変更ではありません。方法contains

だから、複数のコールは、スレッドセーフでありますか?

は、それは本当だ場合:それは(IBM JVMのような)JVMのすべての実装に保証されていますか?

+2

あなたのスレッドが構造的な変更を加えていない場合、問題ではありません:いくつかの他のスレッドが構造的な変更を行っている場合、あなたは*すべてを同期する必要があります* 'contains'への呼び出しを含む*あらゆるスレッドからのアクセス。 –

+0

HashSetの初期化時に 'Collections.unmodifiableSet'を使用しても、実際、私たちは私たちの場合に 'contains'メソッドだけを使うことを確信しています。 HashSetを使用するすべてのスレッド(初期化後)は、 'contains' – lecogiteur

+1

というメソッドのみを使用して、他のスレッドが構造変更を行っているかどうかを確認します。構築時にunmodifiableSetですぐにセットをラップすると、他のスレッドは構造変更を行っていません。 –

答えて

2

は、一般に、単独で読み出し動作の間に並行性レース(したがってコンフリクト)が存在することはできません。読み取り操作と書き込み操作の間に並行性の問題が発生します。したがって、インターリーブされた複数の読み取り操作は常にスレッドセーフです(スレッドセーフのこのような概念が十分に定義されていると仮定した場合)。

ここでは、並行処理の問題があり、これはデータ構造の初期化中です。これは、ケース内で唯一の変更(書き込み操作)と考えることができるためです。次のすべての呼び出しに完全に初期化されたSetが表示されるようにするには、正しく初期化されていることを確認する必要があります。このコンセプトはJavaの「安全なパブリケーション」として定義されており、その詳細についてはhereまたは書籍"Java Concurrency in Practice"の本を読むことができます。

結論として、Collections.unmodifiableSet()は結果を安全な方法でfinalフィールドにパブリッシュします。だから、そう、あなたはすべてのが完全に初期化表示されることを確認することができますSet