ConcrrentHashMap.put方法源码流程图
2021-03-11 17:59:31 34 举报
ConcrrentHashMap.put方法源码流程图
作者其他创作
大纲/内容
f 表示桶位的头结点n 表示散列表数组的长度i 表示key通过寻址计算后,得到的桶位下标fh 表示桶位头结点的hash值
(fh >= 0)
true
条件成立,表示当前桶位是 红黑树代理结点TreeBin
false
(!onlyIfAbsent)
(tab == null || (n = tab.length) == 0)
fh = f.hash
i 表示key使用路由寻址算法得到 key对应 table数组的下标位置,tabAt 获取指定桶位的头结点 f
循环调用
表示红黑树中如果与你插入节点的key 有冲突节点的话 ,则putTreeVal 方法 会返回冲突节点的引用。强制设置binCount为2,因为binCount <= 1 时有其它含义
条件成立表示当前桶位的头结点 为 FWD结点,表示目前map正处于扩容过程中..
将冲突节点的值 赋值给 oldVal
当前循环节点 keye是每次循环处理节点。
cas操作失败,表示在当前线程之前,有其它线程先你一步向指定i桶位设置值了。当前线程只能再次自旋,去走其它逻辑。
oldVal = e.val
n = tab.length
当前元素 与 插入元素的key不一致 时,会走下面程序。
成立,说明当前插入节点的key与红黑树中的某个节点的key一致,冲突了
(binCount >= TREEIFY_THRESHOLD)
(e = e.next) == null
e.val = value
1.更新循环处理节点为 当前节点的下一个节点
binCount != 0
将当前循环的元素的 值 赋值给oldVal
1.统计当前table一共有多少数据2.判断是否达到扩容阈值标准,触发扩容。
tab = initTable();
i = (n - 1) & hash
binCount = 1;
成立:说明循环的当前节点与插入节点的key一致,发生冲突了
((fh = f.hash) == MOVED)
使用sync 加锁“头节点”
条件成立,说明当前桶位就是普通链表桶位。
break
成立,表示当前map中的table尚未初始化..
NullPointerException
成立 表示循环的当前元素的hash值与插入节点的hash值一致,需要进一步判断
2.判断下一个节点是否为null,如果是null,说明当前节点已经是队尾了,插入数据需要追加到队尾节点的后面。
为什么又要对比一下,看看当前桶位的头节点 是否为 之前获取的头结点?为了避免其它线程将该桶位的头结点修改掉,导致当前线程从sync 加锁 就有问题了。之后所有操作都不用在做了。
(f instanceof TreeBin)
(key == null || value == null)
cas操作成功 表示ok,直接break for循环即可
当前桶位 可能是 链表 也可能是 红黑树代理结点TreeBin
调用转化链表为红黑树的方法
return oldVal
((ek = e.key) == key ||(ek != null&&key.equals(ek)))
通过spread方法,可以让高位也能参与进寻址运算。binCount表示当前k-v 封装成node后插入到指定桶位后,在桶位中的所属链表的下标位置 0 表示当前桶位为null,node可以直接放着 2 表示当前桶位已经可能是红黑树
如果binCount>=8 表示处理的桶位一定是链表
p.val = value
说明当前桶位不为null,可能是红黑树 也可能是链表
e.hash == hash
p 表示红黑树中如果与你插入节点的key 有冲突节点的话 ,则putTreeVal 方法 会返回冲突节点的引用。强制设置binCount为2,因为binCount <= 1 时有其它含义,所以这里设置为了2
说明当前线程插入的数据key,与原有k-v发生冲突,需要将原数据v返回给调用者。
1.当前插入key与链表当中所有元素的key都不一致时,当前的插入操作是追加到链表的末尾binCount表示链表长度2.当前插入key与链表当中的某个元素的key一致时,当前插入操作可能就是替换了。binCount表示冲突位置(binCount - 1)
oldVal = p.val;
p!=null
int hash = spread(key.hashCode())int binCount = 0;
(oldVal != null)
synchronized (f)
0 条评论
下一页