put的全程操作:
(1)检查当前table是否初始化。如果没有初始化,首先初始化。设置sizeCtl为-1;然后初始化一个大小为16的数组。
(2)当sizeCtl为负数时,表示结构正在发生变化,所以此时其他线程的操作都会被阻塞,直到sizeCtl变回0;
(3)初始化之后,put值。
(4)如果之前已经初始化了,那么检查当前槽点是否为空,如果为空,cas插入;失败就继续自旋cas;直到成功;
(5)如果当前槽点不为空,检查是否是转移节点,如果是转移节点,那么久等待扩容操作完成;
(6)如果不是转移节点,那么久锁住槽节点,进行插入操作,直到插入完成;
(7)结束后检查是否需要扩容,如果需要就去扩容。
扩容操作:
(1)首先建立一个新的数组,大小是之前的两倍;
(2)然后从当前数组的队尾开始,转移槽点上的值到新数组上;当操作某个槽点时,会把原数组的槽点锁住,保证原数组的槽点不可操作,成功拷贝到新数组时,把原数组赋值为转移节点;
(3)这时,如果有新数据要put到这个槽点,就会发现它是转移节点,就会一直等待;
(4)当所有拷贝完成,就把新数组整个赋值给数组容器。