ConcurrentHashMap(JDK1.8) put()方法
2022-11-08 14:17:59 8 举报
为你推荐
查看更多
ConcurrentHashMap是Java 1.8版本中引入的线程安全的哈希表实现,put()方法用于向该哈希表中添加键值对。当多个线程同时对ConcurrentHashMap进行put操作时,由于其内部采用了分段锁技术,不同段的数据可以独立加锁,从而避免了锁竞争和阻塞,提高了并发性能。此外,ConcurrentHashMap还支持高效的并发读取操作,通过volatile关键字保证变量的可见性,以及使用CAS无锁算法来更新数组元素。总之,ConcurrentHashMap的put()方法是一种高效、可靠的线程安全操作,适用于多线程环境下的应用场景。
作者其他创作
大纲/内容
static final int HASH_BITS = 0x7fffffff保证hash为非负数 后面判断链表需要
putTreeVal
如果数组还未初始化,先对数组进行初始化
tab = initTable()
链表长度大于/等于8,将链表转成红黑树
break
return null结束
对当前桶进行加锁,保证线程安全,执行元素添加操作
if (binCount != 0)
tab == null || (n = tab.length) == 0
如果有空值或者空键,直接抛异常
如果tab为空,调用initTable()方法进行初始化如果tab不为空,就判断所在的槽是否为空,如果是的话,说明是第一个元素,就调用casTabAt()方法直接新建节点添加到Node数组中就可以了如果正在扩容,就帮助扩容如果没有扩容也不为空,就把元素插入槽中,先使用synchronized进行加锁,这个锁的粒度就是数组的具体的一个元素,fh是当前索引位置的hash值,如果大于等于0,说明是链表,否则是红黑树。链表插入会对binCount加一操作,新元素插入尾部,如果key相同覆盖原来的值判断binCount是否大于等于TREEIFY_THRESHOLD(值为8) ,这时候调用treeifyBin()方法考虑将链表转换为红黑树,真正要转为红黑树还要求数组长度大于64
fh >= 0
如果hash计算得到的桶位置没有元素,利用cas将元素添加
putVal
cas+自旋(和外侧的for构成自旋循环),保证元素添加安全
普通链表节点
f instanceof TreeBin
(h ^ (h >>> 16)) & HASH_BITS
oldVal != null
synchronized (f)
自旋
如果是重复键,直接将旧值返回
key == null || value == null
casTabAt
spread(key.hashCode())
如果hash计算得到的桶位置元素的hash值为MOVED,证明正在扩容,那么协助扩容
ConcurrentHashMap(JDK1.8) put操作
判断当前节点是否还是f,有可能被其他线程变成树
树节点,将元素添加到红黑树中
hash计算的桶位置元素不为空,且当前没有处于扩容操作,进行元素添加
遍历链表
(fh = f.hash) == MOVED
添加的是新元素,维护集合长度,并判断是否要进行扩容操作
赋值完成后break
return oldVal结束
binCount >= TREEIFY_THRESHOLD
0 条评论
回复 删除
下一页