2017-01-07 12 views
0

ソースコードConcurrentHashMapJDK1.6に読み込んだとき、putメソッドが値をチェックしているため、readValueUnderLock(e)に到達できませんでした。値がnullの場合は、NullPointerExceptionをスローする必要があります。だから私は何か間違っているかもしれないと思うが、私はそれが何であるか分からない。私は誰かが私に答えることができれば感謝します!なぜConcurrentHashMapのgetメソッドにreadValueUnderLock(e)が存在するのですか?

ここにいくつかのソースコード:

V get(Object key, int hash) { 
    if (count != 0) { // read-volatile 
     HashEntry<K,V> 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; 
} 

V readValueUnderLock(HashEntry<K,V> e) { 
    lock(); 
    try { 
     return e.value; 
    } finally { 
     unlock(); 
    } 
} 

public V put(K key, V value) { 
    if (value == null) 
     throw new NullPointerException(); 
    int hash = hash(key.hashCode()); 
    return segmentFor(hash).put(key, hash, value, false); 
} 

答えて

1

VはEntry.valueの単なるスナップショットです。エントリがまだ完全に構築されていない可能性があります(以前のJava Memory Modelでのダブルチェックロックの問題を考慮)、nullになる可能性があります。これはちょうど極端なケースですが、JREはこれが確実に動作するようにしなければならないので、readValueUnderLockがあります。

PS:時間に追いつく方が良いです。 Javaは進化しており、数ヶ月でJava 9が登場しています。コードベースにはいくつかの大きな変化がありました。時代遅れの知識で頭をいっぱいにすることは良い考えではないかもしれません。

+0

「ConcurrentHashMap」については何も古くはありません。 – chrylis

+1

はい、これは廃止されていませんが、内部実装が大きく変わっています。 Java 8のCHM内で 'HashEntry'や' Segment'を見つけることはできません。Java 6のCHM内部についての知識は時代遅れであり、使用されているハックは後のJavaバージョンでは必要ないかもしれません。あなたのクライアントがJava6だけを必要としていると確信している場合は、Java6をアップグレードすることを決して決して決して決してしないでください。これは一般的なケースではありません。 – glee8e

+0

私は 'double-check'を知っています - シングルトンパターンの実装の一つです。キーワード 'volatile'がなければ、インスタンスはnullではなく、適切な値でもありません(まだ完全には構築されていません)。 'readValueUnderLock'はvolatile(JDK1.6以降のエフェクト)と同じ役割を果たします。 –

関連する問題