11

HashMapのプログラムには、複数のスレッドによってアクセスされ、1 つのスレッドによって設定されることがあります。

例えば:

Map<String, String> myMap = new HashMap<String, String>();

これは、複数のスレッドによってアクセスされます。1 時間に 1 回、1 つのスレッドが以下を呼び出します。

myMap = myRefreshedVersionOfTheMap;

私の質問は、これがスレッドセーフかどうかです。両方のマップが常にキーを持っている場合、存在しない"importantKey"ときに読み取りスレッドがマップにアクセスすることは可能ですか?"importantKey"

編集:

回答のおかげで、この質問は実際にはHashMap. オブジェクト参照の代入についての質問でした。

4

4 に答える 4

11

これはスレッドセーフではありません。パブリッシュの時点以降 (パブリケーションを実行するスレッドの観点から) マップ自体への書き込みはなく、参照の割り当てはアトミックですが、新しいものは安全にパブリッシュされMap<>ていません。特に、それらの要素を追加する方法に応じて、コンストラクター内またはコンストラクター内のいずれかで、その構築中に Map への書き込みがあり、それらの書き込みは他のスレッドで見られる場合と見られない場合があります。 map は他のスレッドに発行されますが、メモリ モデルによると、これは正式には当てはまりません。

オブジェクトを安全に公開するには、オブジェクトの構築、参照の公開、および参照の読み取りの間に発生前の関係を確立する何らかのメカニズムを使用して、外部の世界に伝達する必要があります。公開しても安全であることが保証されています:

  • 静的初期化子からのオブジェクト参照の初期化。
  • それへの参照を final フィールドに格納します。

myMap を宣言した場合、イディオムは安全ですvolatile。安全な公開の詳細については、JCIP (強くお勧めします)、こちら、または同様のトピックに関するこの長い回答をご覧ください。

于 2013-06-20T17:52:28.967 に答える
9

まったく新しいものを作成していて、それを他のスレッドがアクセスしているものにMap割り当てているという意味であれば、そうです。myMap参照割り当てはアトミックです。他のスレッドが a から読み取っている間に aの内容を変更していないため、スレッドセーフです。Map複数のスレッドが a から読み取っているだけMapです。

volatile他のスレッドがキャッシュしないように宣言するだけです。

于 2013-06-20T17:31:16.023 に答える
0

まず、Java の HashMap クラスはスレッド セーフではないため、読み取りと書き込みが同時に行われる保証はありません。

ただし、Java での参照への読み取りと書き込みはアトミックであるため、更新コードが古いマップを変更していない限り、説明したパターンはスレッドセーフである可能性があります。たとえば、次のようにしても問題ありません。

// this refresh code would be thread-safe
Map<String, String> copy = new HashMap<String, String>(myMap);
copy.put(x, y); // change the map
myMap = copy;

// you might also consider
myMap = Collections.unmodifiableMap(copy);
// to make sure that the non-thread-safe map will never be mutated

このパターンで考慮すべきことの 1 つは、myMap フィールドを volatile として宣言して、すべてのスレッドがその変数から読み取るたびに myMap の最新バージョンを取得できるようにすることです。

最後に、他の投稿者が言及しているように、更新コードの複雑さによっては、ConcurrentHashMap の方が優れたアプローチである可能性があります。ConcurrentHashMap の欠点の 1 つは、操作をバッチ処理する方法がないことです。そのため、更新プロセス中のすべての時点での状態がアプリケーションの残りの部分で有効であることを確認する必要があります。

于 2013-06-20T17:29:59.313 に答える
-1

HashMap はスレッドセーフではありません。以下のいずれかを使用できます

  1. コンカレントハッシュマップ。
  2. 外部で同期された HashMap。
  3. スレッドごとに異なる HashMap。

この同様の回答をここで確認してください

于 2013-06-20T17:32:50.570 に答える