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数据结构很简单,从上可知,就是一个链表,可是只容许对数据进行查找,不容许进行修改

相关文章
相关标签/搜索