HashMap在put的时候回调用下面的方法,这个方法是线程不安全的
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}
首先讲一下这个方法:
bucketIndex是该key所对应的数组的位置,table就是数组,Entry是链表的一个节点,因为里面有next属性,所以相当于一个链表,当一个新的元素put的时候,如果产生了hash碰撞,那么会把原来在该索引位置上的元素赋值给一个新的Entry 节点 e,然后创建一个新的 Entry 节点,并把 e 作为新节点的next,而且把这个新节点赋值给 table 的 bucketIndex 位置上,说白了就是把新节点放在链表的头节点,原来的头节点作为新头节点的next
所以这个方法存在线程安全性,当在高并发场景的时候,如果第一个线程和第二个线程同时执行了 Entry<K,V> e = table[bucketIndex]; 这一步的话,那么第二个线程的值会覆盖第一个线程的值,导致第一个线程的put被覆盖
引用其他文章:https://blog.csdn.net/eson_15/article/details/51543812