- 私を困惑させるのはこれです。
ConcurrentHashMap の HashEntry の Java ドキュメント (jdk1.6.0_16)
...値フィールドは最終的なものではなく揮発性であるため、データ競合を介して読み取られたときに、非同期リーダーが初期値ではなく null を表示することは、Java メモリ モデルに関して合法です。これにつながる並べ替えが実際に発生する可能性はほとんどありませんが、Segment.readValueUnderLock メソッドは、同期されていないアクセス メソッドで null (事前に初期化された) 値が見られる場合のバックアップとして使用されます。
ここに ConcurrentHashMap#Segment の get メソッドの実装があります
V get(Object key, int hash) { if (count != 0) { // read-volatile HashEntry e = getFirst(hash); while (e != null) { if (e.hash == hash && key.equals(e.key)) { V v = e.value; if (v != null) return v; return readValueUnderLock(e); // recheck } e = e.next; } } return null; }
そして readValueUnderLock の
V readValueUnderLock(HashEntry e) {
lock();
try {
return e.value;
} finally {
unlock();
}
}
私の読書と理解に基づいて、すべてのスレッドは揮発性変数の最新の値を読み取ります。
では、スレッドはいつ最初の null 値を読み取るのでしょうか? 特に、コンストラクターが完了する前に値が割り当てられる HashEntry では。(HashEntry の参照がそのコンストラクターを決してエスケープしないことにも注意してください。)
ConcurrentHashMap(jdk1.6.0_16)のHashEntryの上記のJavaドキュメントを説明できる人がいます。そして、なぜ特別な予防ロックが必要なのですか?