Question

I wanted to understand how does locking work in Java ConcurrentHashMap. Accordingly to the source-code here, it looks like for every read it is locking the reader using the lock of that particular segment. Have I got it wrong?

V readValueUnderLock(HashEntry<K,V> e) {
    lock();
         try {
             return e.value;
         } finally {
             unlock();
         }
     }
Était-ce utile?

La solution

Every Read is not locked below is documentation of method readValueUnderLock

Reads value field of an entry under lock. Called if value field ever appears to be null. This is possible only if a compiler happens to reorder a HashEntry initialization with its table assignment, which is legal under memory model but is not known to ever occur.

Read in a ConcurrentHashMap does not synchronize on the entire map. Infact traversal does not synchronize at all except under one condition. The internal LinkedList implementation is aware of the changes to the underlying collection. If it detects any such changes during traversal it synchronizes itself on the bucket it is traversing and then tries to re-read the values. This always insures that while the values received are always fresh, there is minimalistic locking if any.

Below is get implementation in this class readValueUnderLock is called only when v is null

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top