HashMap高并发数据丢失的原因

HashMap 进行 put 操作时的流程是:先计算 hashCode 找到桶,然后遍历桶内的链表找到插入位置插入。即先查后写。但凡先查后写的,在并发环境下往往都有并发查询问题

举个例子,
比如有两个待写入的键值对 {“a”: 1, “b”: 2},刚好落到同一个桶里,假设这个桶是 0 号桶,这个桶里之前有一个元素 c。

单线程环境下

我们先查 a 准备写入的位置,查到是 0 号桶的 c 后面的位置,则我们写入 a,即 c.next = a。然后查 b 准备写入的位置,这次查到是 0号桶的 a 后面的位置,写入 b,即 a.next = b。此情景下 a, b 两个元素都能正常被写入。

多线程环境下

a 的查询可能和 b 是同步进行的。
比如,
a 在线程 t1 里,b 在线程 t2 里 线程 t1 的查询里,a 的写入位置是 c 后面,c.next=a
线程 t2 的查询里,b 的写入位置也是 c 后面(因为此刻 a 尚未插入),c.next=b
最终先插入 c 后面的会被后插入的覆盖,a 和 b 两个元素只有一个被实际成功写入,另一个丢了。

ConcurrentHashMap

所以说 hashMap 不能用于多线程环境,它本身就不是为多线程环境设计的。强行用于多线程环境会引发诸多问题。

那么 ConcurrentHashMap 是怎么解决这样的并发问题的呢?其实很简单,就是在写入时对例子中的 0号桶加锁,加锁期间别的线程需要等待锁释放后才能写入这个桶。

比如线程 t1 写入 a 时加了锁,那么线程 t2 必须等待 a 写完才能写入 b, 相当于把这个桶上的并行操作转为串行了。这时 b 的写入位置是 a 后面,a.next=b,a 和 b 都能正常被写入。(这是 jdk1.7 的做法,1.8 改为 CAS了,不再需要锁,不过不属于本问题范畴,这里不详谈)

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Agatha方艺璇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值