0 前言
线程安全的 Map - ConcurrentHashMap,让我们一起研究和 HashMap 相比有何差异,为何能保证线程安全呢.
1 继承体系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gkf7KyhC-1587048420294)(https://user-gold-cdn.xitu.io/2020/4/13/1716f691bd3ef39d “图片标题”)]
与 HashMap 很相似,数组、链表结构几乎相同,都实现了 Map 接口,继承了 AbstractMap 抽象类,大多数的方法也都是相同的,ConcurrentHashMap 几乎包含 HashMap所有方法.
2 属性
bin数组.第一次插入时才延迟初始化.大小始终是2的幂.由迭代器直接访问.
下一个要用的 table;仅在扩容时非null
基本计数器值,主要在没有争用时使用,也用作table初始化竞争期间的反馈.通过CAS更新
table 初始化和扩容的控制
如果为负,则表将被初始化或扩容:
-1用于初始化
-N 活动的扩容线程数
否则,当table为null时,保留创建时要使用的初始表大小,或者默认为0.
初始化后,保留下一个要扩容表的元素计数值.
扩容时要拆分的下一个表索引(加1)
扩容和/或创建 CounterCell 时使用的自旋锁(通过CAS锁定)
Table of counter cells。 如果为非null,则大小为2的幂.
Node节点:保存key,value及key的hash值的数据结构,其中value和next都用volatile修饰,保证可见性
一个特殊的Node节点,转移节点的 hash 值都是 MOVED,-1.其中存储nextTable的引用.在transfer期间插入bin head的节点.只有table发生扩容的时候,ForwardingNode才会发挥作用,作为一个占位符放在table中表示当前节点为null或则已经被移动,