导致HashMap线程不安全的原因可能有以下几种:
Hash碰撞:当多个线程同时使用put方法添加元素的时候,正巧存在两个put的key发生了碰撞(根据hash值计算的bucket一样),那么根据HashMap的存储原理,这两个key会添加多数组的同一个位置,这样其中一个线程put的数据势必会被覆盖导致丢失
扩容:扩容方法也不是同步的,扩容过程中,会新生成一个新的容量的数组,然后对原数组的所有键值对重新进行计算和写入新的数组,之后指向新生成的数组。
当多个线程同时检测到总数量超过门限值的时候就会同时调用resize操作,各自生成新的数组并rehash后赋给该map底层的数组table,结果最终只有最后一个线程生成的新数组被赋给table变量,其他线程的均会丢失。
而且当某些线程已经完成赋值而其他线程刚开始的时候,就会用已经被赋值的table作为原始数组,这样也会有问题。
rehash:Hashmap的Resize包含扩容和ReHash两个步骤,对于ReHash在并发的情况下操作,《Java并发编程的艺术》一书中是这么说的:“hashMap在并发执行put操作会引起死循环,导致CPU利用率接近100%。因为多线程会导致HashMap的Node链表形成环数据结构,一旦形成环数据结构,Node的next节点永远不为空,就会在获取Node时产生死循环”。
详细过程可参考:https://blog.csdn.net/wufaliang003/article/details/80219296
参考: HashMap为什么线程不安全
技术讨论 & 疑问建议 & 个人博客
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,转载请注明出处!
网友评论