数据插入策略
a. 当插入数据时,计算出key的hash值。
b. 如果table不存在,则先初始化table。
c. 通过此hash值求出key应该插入到的链表位置,如果此位置为null,则使用cas方式初始化链表。否则如果此链表hash值为-1,表示正在执行resize,否则锁住链表,如果链表hash值大于等于0,进行常规链表插入,如果hash值小于0,进行树节点的插入。覆盖策略
a. 在插入数据时,如果已存在相同的key则根据onlyIfAbsent参数选择是否覆盖
b. 相同的key需要同时判断,hash相等,并且 == 或者 equals 相等(解决hash冲突问题),才算相等
e.hash == hash && ( (ek = e.key) == key || (ek != null && key.equals(ek)) )
树化策略
a. 在常规插入数据时,binCount为链表size,当树化结构插入时,binCount=2,没有数据插入时,binCount=0。
b. 当binCount>8(树化阈值为8),链表数据结构尝试树化。由1可知只有常规数据插入时才会有树化的可能。
c. 若table元素小于64,则尝试扩容,不进行树化。否则进行树化。锁策略
a. 插入数据时,根据hash取出链表为null,则使用cas方式进行初始化,因为table[]是volatile修饰,保证可见性。
b. 如果链表已存在,则使用内置锁syncronized同步,进行数据的插入size计算
每次更新操作都会触发addCount(long x, int check)
如果大小超过sizeCtl,则进行扩容
volatile counterCells[]统计