ConcurrentHashMap
针对JDK 1.7
和JDK 1.8
版本上实现有不同。先来看看JDK 1.7
版本的ConcurrentHashMap
的底层实现。
JDK 1.7
版本的ConcurrentHashMap
底层维护了:Segments
数组+HashEntry
数组+链表,采用分段锁保证线程安全。
一个ConcurrentHashMap
中有一个Segments
数组,一个Segments
中存储一个HashEntry
数组,每个HashEntry
是一个链表结构的元素。
segment
继承自ReentrantLock
锁。 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一段数据时,其他段的数据也能被其他线程访问,实现了真正的并发访问。可以通过构造函数指定,数组扩容不会影响其他的segment
,get
无需加锁,volatile
保证内存可见性。
JDK 1.8
版本的ConcurrentHashMap
底层维护了:Synchronized
+ CAS
+Node
+ 红黑树。Node
的val
和next
都用volatile
保证,保证可见性。查找,替换,赋值操作都使用CAS
。
1.1 内部属性:
先对ConcurrentHashMap
中的几个重要属性进行了解:
// ConcurrentHashMap 最大容量: private static final int MAXIMUM_CAPACITY = 1 << 30; // ConcurrentHashMap 默认容量(和HashMap一致): private static final int DEFAULT_CAPACITY = 16; // ConcurrentHashMap 最大可能的数组大小: static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 默认的并发级别(不适用,为了兼容之前的版本): private static final int DEFAULT_CONCURRENCY_LEVEL = 16; // 默认的负载因子: private static final float LOAD_FACTOR = 0.75f; // 链表转红黑树阈值: static final int TREEIFY_THRESHOLD = 8; // 红黑树退化成链表的阈值: static final int UNTREEIFY_THRESHOLD = 6; // 红黑树化时,table数组最小值: static final int MIN_TREEIFY_CAPACITY = 64;
除了这些定义的常量值,外有几个关键的内部属性:
table
Node
数组:
和HashMap
不一样的地方是,ConcurrentHashMap
中的table
数组使用了volatile
关键字进行修饰。
// 第一次新增元素时初始化,始终是2的幂: transient volatile Node<K,V>[] table;
除了table
数组外,还提供了nextTable
数组:
// 扩容时用,代表扩容后的数组: private transient volatile Node<K,V>[] nextTable;
Node
节点的特殊hash
值:
// 转移节点的hash值: static final int MOVED = -1; // (红黑)树根节点的hash值: static final int TREEBIN = -2; // 临时保留的hash值: static final int RESERVED = -3; // 普通节点hash的可用位: static final int HASH_BITS = 0x7fffffff;
- 控制
table
初始化和扩容的字段:
// -1 初始化中 // -n 表示n-1个线程正在扩容中 // 0 使用默认容量进行初始化 // >0 使用多少容量 private transient volatile int sizeCtl;
1.2 Node 节点:
这里我们重点关注的是Node
中的两个属性val
和next
。和HashMap
最大的区别就是,这两个属性使用了volatile
关键字进行修饰,保证了这个两个变量的可见性以及有序性。
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; volatile V val; volatile Node<K,V> next; // 构造器、操作方法...... }
关于volatile
关键字的具体作用,需要参考一下JUC
并发部分的文章,这里不过度解析。