ConcurrentHashMap 1.7/1.8

纵饮孤独 提交于 2020-12-13 10:49:24

https://www.cnblogs.com/study-everyday/p/6430462.html

JDK1.7的实现

  • ConcurrentHashMap的数据结构是由一个Segment数组和多个HashEntry组成
    • 每一个Segment元素存储的是HashEntry数组+链表,这个和HashMap的数据存储结构一样
    • HashEntry大小的计算也是2的N次方(cap <<=1)
  • Segment实现了ReentrantLock,也就带有锁的功能,
    • 当执行put操作时,会进行第一次key的hash来定位Segment的位置
      • 这里要进行两次Hash去定位数据的存储位置
  • 计算ConcurrentHashMap的元素大小是一个有趣的问题
    • 第一种方案他会使用不加锁的模式去尝试多次计算ConcurrentHashMap的size,最多三次,
      • 比较前后两次计算的结果,结果一致就认为当前没有元素加入,计算的结果是准确的
    • 第二种方案是如果第一种方案不符合,他就会给每个Segment加上锁,然后计算ConcurrentHashMap的size返回

JDK1.8的实现

  • 直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作
    • JDK1.8中还能看到Segment的数据结构,但是已经简化了属性,只是为了兼容旧版本
    • 当链表的节点数大于8时会转换成红黑树的结构
  • ConcurrentHashMap的初始化其实是一个空实现,并没有做任何事
    • 在put操作中实现,当然ConcurrentHashMap还提供了其他的构造函数,
    • 有指定容量大小或者指定负载因子,跟HashMap一样,这里就不做介绍了
  • 扩容是并发扩容,
    • 调用多个工作线程一起帮助进行扩容
    • 锁加在treeMap的根节点
      • 扩容需要整个数组扩容
      • 一个数组位置(根节点所在位置)一个线程来执行
      • 其他线程扩容后面的微信
    • nextTable:默认为null,扩容时新生成的数组,其大小为原数组的两倍。
    • 只有table发生扩容的时候,ForwardingNode才会发挥作用,
      • 作为一个占位符放在table中表示当前节点为null或则已经被移动

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!