hashmap线程安全吗

Z, ZLW 640

hashmap非线程安全,其线程不安全主要体现在1、JDK1.7并发执行扩容操作时会造成环形链和数据丢失;2、JDK1.8并发执行put操作时会发生数据覆盖。HashMap的扩容操作会重新定位每个桶的下标,并采用头插法将元素迁移到新数组中。头插法是造成死循环和数据丢失的关键。

1、JDK1.7并发执行扩容操作时会造成环形链和数据丢失

HashMap的扩容操作(先扩容在头插法插入)会重新定位每个桶的下标,并采用头插法将元素迁移到新数组中。头插法会将链表的顺序翻转,这也是造成死循环和数据丢失的关键。

JDK1.7的时候采用头插法,多线程同时插入的时候,A线程在插入节点B,B线程也在插入,遇到容量不够开始扩容,重新hash,放置元素,采用头插法,后遍历到的B节点放入了头部,这样形成了环。

2、JDK1.8并发执行put操作时会发生数据覆盖

JDK1.7出现的问题,在JDK1.8中已经得到了很好的解决,JDK1.8直接在resize函数中完成了数据迁移。在进行元素插入时使用的是尾插法然后在扩容。但是以下两种情况造成线程不安全:

  • 两个线程同时插入只有一个成功插入;
  • 可能会造成两次resize(++size>threshold) 。

拓展阅读

如何解决hashmap的线程不安全性

  1. 使用HashTable(效率比较差)
  2. 使用ConcurrentHashMap(比较常用的)
  3. 使用Collections.synchronizedMap()

回复

我来回复
  • 暂无回复内容

注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部