ConcurrentHashMap源码
2024-04-03 20:45:28 28 举报
ConcurrentHashMap源码
作者其他创作
大纲/内容
根据 hash 定位到索引位置
是
步幅为一个线程迁移的连续大小最小为 16。当只有一个核时步幅为数组长度
根据链表进行查询反正是不能再这等着
失败
否
返回头结点 val
synchronized加锁结束
initTable初始化数组
while 循环通过transferIndex,步幅来确定要迁移的位置
Node#find
查询链表一一对比
不是
头节点key是否等于 key
cas 修改lockstate-=4Unsafe#getAndAddInt
添加到链表尾部
成功
put
treeifyBin链表转为红黑树
ForwardingNode#find到nextTable中查找
传入的 nextTab 是否为 null
如果扩容则进行扩容
返回节点
如果当前节点已经是ForwardingNode节点,则继续下一个位置
通过 cas 添加 node
调用节点的 find 方法
当前位置是否为 null
首节点 hash 为-1
hash 相等且 key 相等
get
table 是否为 null
是否是ForwardingNode
设置 nextTable 创建下一个数组
返回 null
通过 CPU 核数来确定stride(步幅)
TreeBin#find红黑树查询
sizeCtl<0
当前节点是红黑树
当前头结点是否发生变更
hash 是否小于 0
sc<0是否有线程正在迁移
当节点已经是红黑树的时候,会设置为 2
根基 hash 拆分成两个链表,并放入到特定的位置
锁住头结点
从头开始继续
spread计算 hash,保证 hash 不小于 0关系到节点类型
扩容后的节点要么在原位置,要么在数组长度+原位置索引
如果有线程在修改,并有线程在等待则唤醒 waiter 线程
有线程正在初始化数组,当前线程等着
节点 hash 小于 0要么是红黑树,要么是在迁移,要么是出 bug 了
TreeNode#findTreeNode红黑树查询节点
使用 synchronized锁住头结点
transfer扩容
到这了说明还没有迁移完成
扩容完成后原数组全是同一个ForwardingNode
创建ForwardingNode该节点的 hash 为-1
根基 hash 拆分成两个TreeNode链表如果链表长度小于 6 则转换为链表,否则转为 TreeBin
当前节点为ForwardingNode则表示在扩容,并且当前位置已经完成迁移
继续对比下一个节点直到没有下一个节点
通过 cas 修改 sizeCtl 获取锁,并初始化数组
头结点 hash 是否不小于 0
把原数组位置设置为ForwardingNode
cas 修改 lockstate+=4
TreeBin维护了一个简单的读写锁,保证读不阻塞,且只有一个线程会修改红黑树
如果迁移完成则用新的数组替换
TreeBin#putTreeVal红黑树添加节点
说明当前又发生了扩容了,设置 nextTable后从新开始
addCount添加计数
spread计算 hash,保证不小于 0
如果当前位置为 null 则把ForwardingNode放进去
是否是树节点
把头结点设置为 TreeBin
当前位置节点树是否大于8
helpTransfer辅助扩容
doubleCheck
是否为TreeBin
hash 所在位置是否为 null
是否有线程正在等待或者改变当前节点
0 条评论
下一页