深入理解ConcurrentHashMap
写在前面
前面分析了 HashMap和Hashtable 。在多线程下, HashMap
的链表可能会出现死循环,所以 HashMap
是线程不安全的。 Hashtable
在所有涉及到多线程操作的都加上了 synchronized
关键字来锁住整个 table
,虽然保证了线程安全,但是无疑效率是地下的。
针对 HashMap
线程不安全的问题, Java
给出的推荐是使用 ConcurrentHashMap
。 ConcurrentHashMap
使用 降低锁粒度
的策略,利用多个锁来控制多个小的 table
(实际上每一个节点都加了锁) ,减少竞争。
ConcurrentHashMap(JDK1.8)
JDK1.8
和JDK1.7
都是使用降低锁粒度
的策略,只是实现不同。在JDK1
.8
中,HashMap
开始使用Node数组
+链表
+红黑树
的数据结构来实现,ConcurrentHashMap
在并发控制上加上了Synchronized
和CAS
操作(可以参考同步锁,乐观锁,悲观锁)。
内部存储结构 Node
transient volatile Node<K,V>[] table; 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; } // 不允许修改value值 public final V setValue(V value) { throw new UnsupportedOperationException(); } /* * Virtualized support for map.get(); overridden in subclasses. * 增加find方法辅助get方法 ,HashMap中的Node类中没有此方法 */ Node<K,V> find(int h, Object k) { Node<K,V> e = this; if (k != null) { do { K ek; if (e.hash == h && ((ek =