1.CurrentHashMap 数据结构
- 抛弃了 JDK 1.7 中原有的 Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。
2 将 JDK 1.7 中存放数据的 HashEntry 改为 Node,但作用是相同的。
2 put方法
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException(); // 键或值为空,抛出异常
// 键的hash值经过计算获得hash值,这里的 hash 计算多了一步 & HASH_BITS,HASH_BITS 是 0x7fffffff,该步是为了消除最高位上的负符号 hash的负在ConcurrentHashMap中有特殊意义表示在扩容或者是树结点
int hash = spread(key.hashCode());
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
// 无限循环
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0) // 表为空或者表的长度为0
// 初始化表
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
// 表不为空并且表的长度大于0,并且该桶不为空
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null))) // 比较并且交换值,如tab的第i项为空则用新生成的node替换
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED) // 该结点的hash值为MOVED
// 进行结点的转移(在扩容的过程中)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) {
// 加锁同步
if (tabAt(tab, i) == f) {
// 找到table表下标为i的结点
if (fh >= 0) {
// 该table表中该结点的hash值大于0
// binCount赋值为1
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
// 无限循环
K ek;
if (e.hash == hash &&a