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 条评论
 下一页
  
   
   
   
   
  
  
  
  
  
  
  
  
 