ConcurrentHashMap源码解析,多线程扩容 (5)

领取完任务之后就开始处理,如果桶为空就设置为 ForwardingNode ,如果不为空就加锁拷贝,只有这里用到了 synchronized 关键字来加锁,为了防止拷贝的过程有其他线程在put元素进来。拷贝完成之后也设置为 ForwardingNode节点。

如果某个线程分配的桶处理完了之后,再去申请,发现 transferIndex = 0,这个时候就说明所有的桶都领取完了,但是别的线程领取任务之后有没有处理完并不知道,该线程会将 sizeCtl 的值减1,然后判断是不是所有线程都退出了,如果还有线程在处理,就退出

直到最后一个线程处理完,发现 sizeCtl = rs<< RESIZE_STAMP_SHIFT 也就是标识符左移 16 位,才会将旧数组干掉,用新数组覆盖,并且会重新设置 sizeCtl 为新数组的扩容点。

以上过程总的来说分成两个部分:

分配任务:这部分其实很简单,就是把一个大的数组给切分,切分多个小份,然后每个线程处理其中每一小份,当然可能就只有1个或者几个线程在扩容,那就一轮一轮的处理,一轮处理一份

处理任务:复制部分主要有两点,第一点就是加锁,第二点就是处理完之后置为ForwardingNode来占位标识这个位置被迁移过了。

2.7 jdk8 的协助扩容 helpTransfer()方法

如果说 put 的时候发现数组正在扩容,会执行 helpTransfer 方法,也就是这个线程来帮助进行扩容。

ConcurrentHashMap源码解析,多线程扩容

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpswjs.html