源码解析 HashMap 的线程安全问题,2024年最新毕业设计选题

现在我们通过源码看下为什么 jdk1.7 中Hashmap 在多线程的情况下扩容会造成死循环,我们直接看源码:

我们简单解释下, 在Hashmap放入元素的时候会有一个 addEntry 的方法, 里面会判断当 Hashmap 中的元素个数达到threshold 阈值的时候, 会进入resize 扩容方法,长度为原来的2倍。在 resize 中我们可以看到首先创建了一个 Entry 数组 newTable,长度为newCapacity,然后会进入 transfer 方法将原来数组中的元素转换到新数组 newTable中,现在我们着重看下transfer 方法:

方法不长,总共只有15行代码,但却是造成死循环的关键地方。 红框中的代码就是造成HashMap死循环的原因,现在我们假设原数组中的第一个元素为一个链表 2–>4,如下图所示:

    2--->4 

现在我们复现一下它是如何转换元素的,假设rehash 为 false,我们看下while 中的第一次遍历是什么样的:

上图可以看到e 为元素2,e.next 为元素 4,而 newTable 为新数组,所以 newTable[i] 是为null 的,while中第一次遍历结束后,我们看下新数组的元素存储情况:

   2--->null   

现在我们看下while 中的第二次遍历:

上图中可以看到 e 为元素4 ,而由于元素4和元素2是在原数组的同一个位置中的,所以他们的 e.hash 的值是一样的,这样算出来的下标 **i 也是一样的,**这样 newTable[i] 就是上一个元素 2。 所以 e.next=2,   newTable[i]=4 , 继续往下走,next 为null则循环结束。我们继续看下新数组中的元素存储情况:

   4--->2   

可以看到链表中的元素被反转了过来,这是因为jdk1.7 中HashMap 在扩容时转换元素的时候,若同一个位置有多个元素,则会采用头插法方式将元素放入新数组,也就是元素始终会在原来元素的头部插入。

我们假设现在有A,B2个线程,A 线程第一次循环结束后,在执行到592行的时候被挂起了。现在B线程进来执行完了2次循环,将4指向2,B结束,A继续执行,就出现2–>4, 4–>2的死循环情况。

我们继续看下jdk1.8 Hashmap 在多线程的情况下扩容的操作源码:

话不多说,直接看 resize 方法:

在查看resize方法时,突然觉得有可以优化的点,于是写了这篇resize优化,虽然推理过程不准确的,但整个思考过程比较完整,有兴趣的可以看看。

由于处于同一位置的哈希值大部分情况是不同的,而 e.hash & oldCap 只会有2种情况,等于0和不等于0,所以采用 loHead,loTail 和 hiHead,hiTail 这四个变量进行区分,而 loTail.next = null; 和  hiTail.next = null; 这2行的效果一样都是为了避免数据重复。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
img
img
img

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
img

,每个节点里面都包含素材文档、项目源码、讲解视频**

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-llnSWsxN-1712585489145)]

  • 24
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值