ConcurrentHashMap

一 HashMap 

   衆所周知 HashMap 的查找效率爲O(1)。可是HashMap非線程安全,在併發狀況下,擴容時可能破壞鏈表的指針,造成環狀鏈。數組

  Hashtable 是線程安全的。看一下 Hashtable 的源碼安全

  get操做數據結構

  

put 操做併發

get 和 put 操做 都是經過加 synchronized 來實現線程安全的。至關於給整個hash 表加了一把鎖。就算線程都是讀操做,也是互斥的。性能比較差。高併發

二  ConcurrentHashMap

  在JDK 1.6 的版本中採用鎖分段的機制,實現高併發。底層採用 數組+鏈表+紅黑樹的數據結構。性能

 

Segment 經過繼承ReentrantLock 來實現加鎖優化

 

JDK 1.8 中拋棄了上面的數據結構,採用CAS+Synchronized來保證併發更新的安全,底層仍然採用this

數組+鏈表+紅黑樹的數據結構。整個看起來像是優化的Hashtable。spa

 

/**
 * Key-value entry.  This class is never exported out as a
 * user-mutable Map.Entry (i.e., one supporting setValue; see
 * MapEntry below), but can be used for read-only traversals used
 * in bulk tasks.  Subclasses of Node with a negative hash field
 * are special, and contain null keys and values (but are never
 * exported).  Otherwise, keys and vals are never null.
 */
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val;
    volatile Node<K,V> next;

    Node(int hash, K key, V val, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.val = val;
        this.next = next;
    }

    public final K getKey()       { return key; }
    public final V getValue()     { return val; }
    public final int hashCode()   { return key.hashCode() ^ val.hashCode(); }
    public final String toString(){ return key + "=" + val; }
    // 不容許進行set 操做
    public final V setValue(V value) {
        throw new UnsupportedOperationException();
    }

    public final boolean equals(Object o) {
        Object k, v, u; Map.Entry<?,?> e;
        return ((o instanceof Map.Entry) &&
                (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
                (v = e.getValue()) != null &&
                (k == key || k.equals(key)) &&
                (v == (u = val) || v.equals(u)));
    }
 /**
     * Virtualized support for map.get(); overridden in subclasses.
     */
    至關於map 的 get() 方法
    Node<K,V> find(int h, Object k) {
        Node<K,V> e = this;
        if (k != null) {
            do {
                K ek;
                if (e.hash == h &&
                    ((ek = e.key) == k || (ek != null && k.equals(ek))))
                    return e;
            } while ((e = e.next) != null);
        }
        return null;
    }
}

能夠看到   volatile V val; volatile Node<K,V> next;  線程

val  和 next 在擴容時會發生變化,加上volatile 來保證內存的可見性和禁止指令的重排序

Node數據結構很簡單,從上可知,就是一個鏈表,可是隻容許對數據進行查找,不容許進行修改

相關文章
相關標籤/搜索