HashMap底层是一个Entry数组,一旦发生Hash冲突的的时候,HashMap采用拉链法解决碰撞冲突。
通过Entry内部的next变量可以知道使用的是链表,如果多个线程,在某一时刻同时操作HashMap并执行put操作,而有大于两个key的hash值相同,这个时候需要解决碰撞冲突,而采用拉链法解决碰撞冲突,这个时候两个线程如果恰好都取到了对应位置的头结点,而最终两个数据中势必会有一个会丢失。
HashMap扩容方法也不是同步的,在扩容过程中,会新生成一个新的容量的数组,然后对原数组的所有键值对重新进行计算和写入新的数组,之后指向新生成的数组。当多个线程同时检测到总数量超过阈值的时候就会同时调用resize操作,各自生成新的数组并rehash后赋给该map底层的数组table,最终只有最后一个线程生成的新数组被赋给table变量,其他线程的均会丢失。而且当某些线程已经完成赋值而其他线程刚开始的时候,就会用已经被赋值的table作为原始数组。