2

ConcurrentHashMapjdk 7のソース コードを調べていますが、いくつか質問があります。StackOverFlow の CHM に関するすべての質問を既に確認しましたが、答えが見つかりませんでした。

  1. get()CHM での操作は、他のスレッドによって正しい値を取得することが保証されていput()ますか? synchronizednull値が表示されない限り、getはそうではないので、私はこれを求めています。同じレコードが他のスレッドによって更新され、get がロックで使用されることを保証する null 値はどのようになっていますか?

  2. これはHashEntry、キーと値が格納される静的クラスに関連しています。

    を。なぜこのクラスは最終クラスなのですか? 誰もそれをサブクラス化しないようにするためだけですか? 誰かがそれをサブクラス化するとどうなりますか? 何か問題がありますか?

    b. 次のフィールドを final にすることは、スレッド セーフを実現するのにどのように役立ちますか?

    c. キーも最終的なのはなぜですか?(Key が final である理由もわかりませんHashMap)

4

1 に答える 1

6

CHM での get 操作は、他のスレッドによって put の正しい値を取得することが保証されていますか?

put()への呼び出しの前に が完了している限り、確実に保証されget()ます。CHM はvolatileアクセスやその他のロックを内部的に使用して、必ずしもsynchronizedキーワードではなく、データが確実に同期されるようにします。

null値が表示されない限り、getは同期されないため、これを求めています。同じレコードが他のスレッドによって更新され、get がロックで使用されることを保証する null 値はどのようになっていますか?

このjavadocを参照していると思います:

値フィールドは最終的なものではなく揮発性であるため、Java メモリ モデルに関しては、非同期リーダーがデータ競合を介して読み取るときに初期値ではなく null を表示することは正当です。これにつながる並べ替えが実際に発生する可能性はほとんどありませんが、Segment.readValueUnderLock メソッドは、同期されていないアクセス メソッドで null (事前に初期化された) 値が見られる場合のバックアップとして使用されます。

これは、値が最終的なものではないことを説明しようとしているため、コンストラクターでの初期化の順序が変更され、リーダーに null 値が表示される可能性があります。これが、CHM が null 値を格納できない理由だと思います。これにより、null をテストしてから、synchronizedブロック内で別の get を実行できます。

並べ替えられたコンストラクターの詳細については、次を参照してください:インスタンスの初期化と共有変数への代入の並べ替えは可能ですか?

なぜHashEntryクラスはファイナルなのですか?誰もそれをサブクラス化しないようにするためだけですか?

はい。これにより、クラスをサブクラス化できなくなります。これにより、不変性が保証されます。誰かがそれをサブクラス化すると、フィールドの可視性が変更され、同時実行契約が破られる可能性があります。

次の [[field]] を final にすることは、スレッドセーフを得るのにどのように役立ちますか?

フィールド (およびフィールドとnext同様) は、フィールドがコンストラクターで完全に初期化されることを保証するためです。これにより、スレッドの安全性が向上します。これは、オプティマイザーがコンストラクターの最後を超えて初期化を並べ替えることができず、すべてのスレッドがデータを参照できることが保証されているためです。keyhashfinal

フィールドに関する情報と、フィールドが上書きを許可しないことvalueを防ぐ方法については、上記を参照してください。finalput(...)

キーも最終的なのはなぜですか?(キーが HashMap で最終的な理由もわかりません)

と同じ答えHashEntry

于 2013-08-30T20:20:59.353 に答える