10

私は昨日から並行性について読んでいて、多くのことを知りません...しかし、いくつかのことが明らかになり始めています...
ダブルチェックロックが安全ではない理由を理解しています(まれな状態が発生する可能性は何ですか)が、 volatile は 1.5 + で問題を修正します....
しかし、これはputifAbsent

お気に入り...

myObj = new myObject("CodeMonkey");
cHashM.putIfAbsent("keyy",myObj);  

次に、これにより、myObj別のスレッドがcHashM.get()???を実行したときに 100% 初期化されることが保証されますか 参照が完全に初期化されていない可能性があるため(ダブルチェックロックの問題)

4

4 に答える 4

5

呼び出しconcurrentHashMap.get(key)てオブジェクトが返された場合、そのオブジェクトは完全に初期化されていることが保証されます。各 put (または putIfAbsent) は、バケット固有のロックを取得し、要素をバケットのエントリに追加します。

コードを調べてみると、get メソッドがこれと同じロックを取得していないことがわかります。したがって、時代遅れの読み取りが存在する可能性があると主張できますが、それも真実ではありません。ここでの理由は、エントリ自体の値が揮発性であるためです。そのため、最新の情報を確実に入手できます。

于 2011-05-13T20:28:37.990 に答える
5

putIfAbsentのメソッドConcurrentHashMapは、check-if-absent-then-set メソッドです。これはアトミック操作です。しかし、次の部分に答えるには: 「これにより、別のスレッドが cHashM.get() を実行するときに myObj が 100% 初期化されることが保証されますか?」、オブジェクトが HashMap に配置されるタイミングによって異なります。通常、事前発生の優先順位があります。つまり、オブジェクトがマップに配置される前に呼び出し元が最初に取得された場合はnull返され、そうでない場合は値が返されます。

于 2011-05-13T20:29:57.330 に答える
2

ドキュメントの関連部分は次のとおりです。

メモリの一貫性の影響:他の同時コレクションと同様に、オブジェクトをキーまたは値としてConcurrentMapに配置する前のスレッドでのアクションは、別のスレッドでのConcurrentMapからのオブジェクトへのアクセスまたは削除に続くアクションの前に発生します。

- java.util.ConcurrentMap

だから、はい、あなたはあなたの起こる前の関係を持っています。

于 2011-05-13T21:01:41.793 に答える
1

私はこれに関する専門家ではありませんが、Segmentinの実装ConcurrentHashMapを見ると、スレッド間の適切な可視性を確保するためにvolatileフィールドが使用されているように見えます。countすべての読み取り操作はcountフィールドを読み取る必要があり、すべての書き込み操作はフィールドに書き込む必要があります。クラスのコメントから:

したがって、読み取り操作はロックせずに続行できますが、
揮発性物質の選択された使用について、完了したことを確認する
他のスレッドによって実行される書き込み操作は、
気がついた。ほとんどの場合、「カウント」フィールドは、
要素の数、その揮発性変数として機能します
視認性を確保。これは便利です。
とにかく、多くの読み取り操作で読み取る必要があります。

   - すべての (非同期の) 読み取り操作は、最初に
     「カウント」フィールドであり、次の場合はテーブル エントリを参照しないでください。
     それは0です。

   - すべての (同期された) 書き込み操作は、
     ビンを構造的に変更した後の「カウント」フィールド。
     操作は、可能性のあるアクションを実行してはなりません
     同時読み取り操作が一時的に見えるようにする
     一貫性のないデータ。これは、
     Map での読み取り操作。例えばノーオペレーション
     テーブルが大きくなったことを明らかにすることができますが、しきい値は
     まだ更新されていないため、原子性はありません
     読み取りに関するこれの要件。
于 2011-05-13T20:27:19.823 に答える