java基础随笔

来源:互联网 发布:淘宝店铺直播招人 编辑:程序博客网 时间:2024/06/11 22:48

ConcurrentHashMap如何实现线程安全?

一开始以为ConcurrentHashMap实现线程安全和别的容器一样,也是通过sychronized实现的。打开ConcurrentHashMap的源码,没有见到一个sychronized关键词。然后就看了下源码,就从最开始的put看吧。

public V put(K key, V value) {        Segment<K,V> s;        if (value == null)            throw new NullPointerException();        int hash = hash(key);        int j = (hash >>> segmentShift) & segmentMask;        if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck             (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment            s = ensureSegment(j);        return s.put(key, hash, value, false);    }
put的时候,可以看出,会先定义一个segment,最后再调用segment的put方法。segment的put方法如下:

final V put(K key, int hash, V value, boolean onlyIfAbsent) {            HashEntry<K,V> node = tryLock() ? null :                scanAndLockForPut(key, hash, value);            V oldValue;            try {                HashEntry<K,V>[] tab = table;                int index = (tab.length - 1) & hash;                HashEntry<K,V> first = entryAt(tab, index);                for (HashEntry<K,V> e = first;;) {                    if (e != null) {                        K k;                        if ((k = e.key) == key ||                            (e.hash == hash && key.equals(k))) {                            oldValue = e.value;                            if (!onlyIfAbsent) {                                e.value = value;                                ++modCount;                            }                            break;                        }                        e = e.next;                    }                    else {                        if (node != null)                            node.setNext(first);                        else                            node = new HashEntry<K,V>(hash, key, value, first);                        int c = count + 1;                        if (c > threshold && tab.length < MAXIMUM_CAPACITY)                            rehash(node);                        else                            setEntryAt(tab, index, node);                        ++modCount;                        count = c;                        oldValue = null;                        break;                    }                }            } finally {                unlock();            }            return oldValue;        }
每个segment里面有一个hashtable,操作的时候会把segment里面的hashtable锁住。


现在就可以理解为,ConcurrentHashMap包含多个segment,每个segment里包含一个hashtable。当对其中一个key进行操作时,即可以理解为对相应的segment进行操作,同时会对其上锁。如果后续有第二个人对该key操作,则需等待锁的释放。相对于别的有锁的map,ConcurrentHashMap是锁定当前正在使用的segment(正在使用的key),而别的map可能是锁定整个map。