ConcurrentHashMap(JDK1.7) put()方法
2022-11-07 19:02:11 7 举报
为你推荐
查看更多
ConcurrentHashMap(JDK1.7) put()方法
作者其他创作
大纲/内容
node.setNext(first)
(k = e.key) == key || (e.hash == hash && key.equals(k))
return oldValue
不为空
setEntryAt
e == null
没有下一个节点,并且也不是重复元素,创建HashEntry对象,不再遍历
e = e.nextretries还是<0
node == null
int index = (tab.length - 1) & hash
oldValue = null; break;
使用ReentrantLock的tryLock()、unlock()、lock() 在put方法中通过UNSAFE.putOrderedObject方法操作Segment[]和HashEntry[]保证线程安全
e = e.next
retries < 0
以自旋的方式,将创建的Segment对象放到Segment[]中,确保线程安全
是重复元素
否
unlock()
死循环遍历链表
取hash的低位,计算HashEntry[]的索引
头插法关联即可
是
头插法
将当前添加的元素对象,存入数组角标位,完成头插法添加元素
scanAndLockForPut
获取索引位的元素对象
while (!tryLock())
rehash(node)
别的线程获取锁,重新遍历
retries = 0
hash(key)计算两个数组的索引
否则遍历下个e
结束
tryLock失败
++retries > MAX_SCAN_RETRIES如果尝试获取锁的次数过多,直接阻塞,直到有线程unlock()lock() 默认64次
如果是重复元素,覆盖原值break;
retries = 0,继续自旋
j处Seg已创建
s=ensureSegment
node != null
创建当前添加的键值对的HashEntry对象
再次判断seg目前是否为空
scanAndLockForPut方法的目的就是未获取到锁的线程不要闲着,去创建HashEntry。如果key相同,领先的线程未设置好value,e == null,后面的线程会覆盖value;领先的线程如果设置好value,后面的线程不会创建HashEntry
(hash >>> segmentShift) & segmentMask因为一个键要计算两个数组的索引,为了避免冲突,这里取高位计算Segment[]的索引
e != null
int j = (hash >>> segmentShift) & segmentMask
获取不到锁就自旋
判断是否需要扩容
获取到的元素为空
一次哈希
当前添加的键值对的HashEntry对象已经被其他线程创建
key相同
创建HashEntry对象
开始
判断该索引位的Segment对象是否创建
以0角标位的Segment为模板创建segment
++retries > MAX_SCAN_RETRIES
tryLock()
二次哈希
ConcurrentHashMap(JDK1.7) put操作
0 条评论
回复 删除
下一页