安乗の値をjava.util.HashMapから複数のスレッド(変更)?
-
01-07-2019 - |
質問
場合がございますので地図を構築するとともに、一方で初期化されません再度修正。また、アクセス(get(キー)から複数のスレッド)。でも安全に使用 java.util.HashMap
このよう?
(現在、私は幸せを java.util.concurrent.ConcurrentHashMap
, い測定を改善する必要性がだんだ単純な HashMap
うまいます。そのため、この問題は ない "エキゾーストマニフォールド、マ?"では、性能ます。むしろ、問題は"遊びに来たいと言っていて安全ですか?")
解決
おムの安全 場合にだけ、その への参照 HashMap
は 安全に公開.なものに関する炉内構造物の HashMap
そのもの 安全な出版 お得にどのように構築のスレッドを基準に地図に見えるその他のスレッド)。
基本的には、唯一のレースはこちらの建設に HashMap
他の読書のスレッドのアクセスする前でした。多くの議論がどうなるのmapオブジェクトがこれとは関係ないかな変更では、興味深い部分はどのように HashMap
参考掲載しています。
例えば、想像を公開する地図のようになります:
class SomeClass {
public static HashMap<Object, Object> MAP;
public synchronized static setMap(HashMap<Object, Object> m) {
MAP = m;
}
}
...やあ setMap()
呼び出され、地図、その他のスレッドを使用 SomeClass.MAP
アクセス地図をチェックのためのnullの場合のようになります:
HashMap<Object,Object> map = SomeClass.MAP;
if (map != null) {
.. use the map
} else {
.. some default behavior
}
この 安全ではありません ものであろうが表示されています。問題はありません が起こる前に との関係のセット SomeObject.MAP
その後の読み取別のスレッドので、読みのスレッドが無料に部分的に構築す。これでいい 何 でも実際にはない を読むスレッド、無限ループ.
安全に公開し、マップに必要なものを が起こる前に との関係 文書の参照 の HashMap
( 出版 やその後の読者を参照する(すなわち、消費).便数に限りあり易い-覚えていな 達成 その[1]:
- 交換の基準により適切なロック分野環太平洋の17.4.5)
- 利用静的な初期化子の初期化店環太平洋の12.4)
- 交換の参照を介して揮発分野環太平洋の17.4.5いており、その結果、この原則のAtomicX授業
- 値を初期化への最終分野環太平洋の17.5).
ものに興味深いのためのシナリオにおいては(2),(3)や(4)とも関連しています。特に、(3)適用に直接コードしてい上:た場合の変換に関する宣言 MAP
:
public static volatile HashMap<Object, Object> MAP;
そのすべてが供給でき:読者が見 非nullの場合 値は必ずし が起こる前に との関係本店 MAP
この店舗の地図を設定する処理です。
その他の方法の変更の意味の方法は(2)を使用して静initalizer)(4)使用 最終)ことを意味するも設定できません MAP
動的に行います。ない場合 必要 これを実行するには、単にそれを宣言する MAP
として static final HashMap<>
または保証され安全です。
実際にルールは簡単のための安全"へのアクセスなオブジェ":
発表する場合、オブジェクトではない 本質的に不変なので (すべての分野に宣言された final
):
- また作成ができるオブジェクトを指定された瞬間の宣言a:う
final
分野を含むstatic final
静ものとします。 - たい割り当てるオブジェクト後、その参照がすでに可視:利用揮発性分野b.
しようとしています。
実際に、非常に効率的です。の使用 static final
の分野で能力を発揮することで、JVMの想定価値は変わらず生命のプログラムを最適化します。の使用 final
会員の分野で 最 アーキテクチャの分野に相当する通常の分野の読みん抑制作用がc.
最後に、利用 volatile
おいても影響:のないハードウェア障壁は多くのアーキテクチャ(などのx86、特に許可しない読み込みにパスを読み込み)ですが、一部の最適化、並べ替えが遅れる可能性がありコンパイル時間が、この効果は小さい。交換ですから、一緒に試してみましょうような使い方のために-するだけでなく安全に公開一 HashMap
, できる店も多くありません更新 HashMap
sしたいと同一の参照を保証するすべての読者のままに安全に掲載す。
詳gory参照 Shipilev または このFAQによるMansonとGoetz.
[1]を直接引用から shipilev.
a 楽しそう複雑なもうとして選択することができ、参照で施工時間のいずれかで宣言のポイントまたはコンストラクタ(会員の分野あるいは静的な初期化子(static).
b 任意にしてお使いいただけます synchronized
方法を取得および設定するための、または AtomicReference
ももちゃの最小限の作業できます。
cアーキテクチャもあ非常に弱いメモリーモデル私見 す, アルファが必要とするタイプの読みの壁前 final
読み取りでも、これは非常に珍しいです。
他のヒント
Jeremy Manson、そのJavaメモリのモデルは、三つの部分のブログはこの話題が本質的にいう質問に"はこれを安全にアクセス不変のHashMap"に答えることがあります。いてを参照してください回答のあったが,その問いは"こんなにも"より、私のHashMap不変なので".その答えがっくりしま-Java比較的複雑なルールの決定に不変性.
詳しい情報になるように読みJeremyのブログの投稿:
第1部に不変性をJava:http://jeremymanson.blogspot.com/2008/04/immutability-in-java.html
部2不変性をJava:http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-2.html
第3部に不変性をJava:http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-3.html
の読み込みからの同期観点かないメモリの視点からこれは、広く誤解の中Javaベースのシステム開発を含むこStackoverflow.(遵守の格付け この答え のための証明することにあります。)
場合は他のスレッド走行も見えない最新のコピーのHashMapがない場合、メモリに書き出す現在のスレッドメモリに書き込みが発生しているのに同期は揮発性にはキーワードを通しての用途のjava並行処理を構築します.
後かみっこ java doc (重鉱):
この実装はしない 同期化されます。 複数のスレッド アクセスのハッシュ地図が同時に 少なくとも一つのスレッドの変数を変更する機能を提供する 地図の構造が必要です 外部で同期. (構造 修正の操作をする を追加または削除す一つ以上のマッピングに関連する値を単に変更する キースのインスタンスで 含まれない構造 変更になります。
このようなことをすることもできますので、その会話の書があります。
一ノる特定の状況下では、get()からunsynchronized HashMapできるのではないかとまで無限ループを実行します。ここで起きる場合併put()の原因に焼き直さい。
http://lightbody.net/blog/2005/07/hashmapget_can_cause_an_infini.html
がねじれますが。で安全にアクセスの地図ものですが、一般的な保証されるすべてのスレッドを見同じ状態にその値)のHashMap.ここにマルチプロセッサシステムの変更は、HashMapによるスレッド(例えば、このょう)することができるCPUキャッシュになれるスレッドの走行その他のCpu、メモリのフェンス動作を行いますの確保キャッシュコヒーレンス."Java言語仕様は明示的にこのこのセクションのロックを取得する(同期(...)を光メモリのフェンス動作します。そのため、この後populatingのHashMapそれぞれのスレッドを取得しずをロックでOKそのときからアクセスのHashMapから任意のスレッドまでのHashMapが変更されます。
による http://www.ibm.com/developerworks/java/library/j-jtp03304/ #初期化安全性お客様のHashMapの最終分野のコンストラクタを終了する安全に載っています。
...新しいメモリモデルがあり何かに似て起こる前の関係を書の最終分野のコンストラクタの負荷の共有を参照するオブジェクトを別のスレッドの....
でのシナリオで記述は置する必要がありますの束のデータをマップできたらpopulatingできて変更できません。そのひとつである"安全"を意味するだけ強化となっているので処理として不変の)への参照 Collections.unmodifiableMap(originalMap)
がんを作り上げていきたいと考えていので不変です。
例かどうかマップに失敗する場合併用は、回避策を提案して、チェックアウトはこのバグパレード入力: bug_id=6423457
ることを警告されてもシングル-レコードの交換ConcurrentHashMap、HashMapは安全です。ConcurrentHashMap禁止としてnullのキーや値とします。HashMapないことを禁止していない).
このように考える状況既存のコードが追加nullの場合、収集時にアクセス-コントロールにより、おそらく失敗の場合など)において、コレクションに記載の機能性活動しています。
とはいえ、だか同時に読み込みからHashMapの安全を見守ることでした。
[編集:による"同時に読み込み"というのは、ありませんも兼任しています。
その他の回答方法を説明しめます。片道の地図は不変なので、も必要ありません。例えば、JSR133記憶モデルに明示的に定義さかのスレッドを同期行動に意味が変化したスレッドの開始時にスレッドBは可視スレッドB.
私の意図はないと矛盾者詳細な回答のJavaメモリのモデルです。この答えは一意するもののほからの並行処理で問題が少なくとも一つのAPI差ConcurrentHashMap、HashMapがscupperも単一のネジ付きるプログラム交換の一つにも見出すことができる。]
http://www.docjar.com/html/api/java/util/HashMap.java.html
こちらのソースHashMap.まだありませんロック/ロックミューテックスコードはあります。
することが大丈夫からの読み込み、HashMapは、並行マルチスレッドの状況でコーヒーのサービスもよかった利用ConcurrentHashMapがあった場合複数の書き込みます.
していただきました興味深いである。純ハッシュテーブルおよび辞書<K,V> て同期のコードです。
の場合は初期化全てが同期されますと保存されます。
次のコードは保存のクラスローダを同期
public static final HashMap<String, String> map = new HashMap<>();
static {
map.put("A","A");
}
以下のコードを保存すので、揮発性を同期します。
class Foo {
volatile HashMap<String, String> map;
public void init() {
final HashMap<String, String> tmp = new HashMap<>();
tmp.put("A","A");
// writing to volatile has to be after the modification of the map
this.map = tmp;
}
}
これらの作業員がその変数の最終なので最終的にも激しい動きを示している。場合はメソッドはコンストラクタです。