HashMap为什么会发生线程不安全?如何在多线程的情况下安全的使用HashMap?

我们知道HashMap底层的数据结构是数组+链表/红黑树,默认初始容量是16,当数组中的元素大于hashMap的初始容量乘以加载因子时(加载因子默认是0.75),HashMap就会进行扩容,容量变为原来的2倍,然后将原来的数据重新映射到新的桶里面,然后将原来的桶逐个置为null,使得引用失效。也就是在hashMap进行扩容的时候容易发生HashMap线程不安全。HashMap线程不安全主要会产生以下两种情况:1、在多线程的环境下,进行put()的时候会导致多线程的数据不一致。2、在多线程的环境下,对HashMap进行get操作可能因为扩容而引起死循环。

1、在多线程的环境下,进行put()的时候会导致多线程的数据不一致。

例如有A、B两个线程,首先假设A获得CPU的执行权,A开始向HashMap中添加数据,先计算key的hash值,计算元素落到桶的索引坐标,然后获取到了桶里面的链表头结点,此时线程A的时间片用完了,线程B获得了cpu的执行权,线程B和线程A一样执行操作,只不过B成功的将元素添加到HashMap中了,此时线程A获得cpu执行权,假设A线程要插入的元素计算得到在桶中的索引和线程B插入元素的索引一样,线程B插入成功之后,线程A执行,此时线程A插入的数据会覆盖掉线程B插入的数据,这样线程B插入的记录就会凭空消失,造成了数据不一致。

2、在多线程的环境下,执行get()元素的时候可能会因为扩容引起死循环

HashMap是采用链表解决Hash冲突,因为是链表结构,那么就容易形成闭合链路,这样在循环的时候只要有线程对这个HashMap进行get操作就会产生死循环。在单线程的情况下,只有一个线程对HashMap数据结构进行操作,是不可能产生闭合回路的,当put的时候,如果size>initialCapacity*loadFactor,那么这时候HashMap就会进行rehash操作,随之HashMap的结构就会发生翻天覆地的变化。很有可能两个线程就是在这个时候同时出发rehash操作,产生了闭合回路。

如果想在多线程的环境下使用HashMap,该怎么办?

1、使用ConcurrentHashMap

2、使用Collections.synchonizedMap(Map<K,v>  m)方法将HashMap变成一个线程安全的map。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值