当前位置: 首页 > 网络应用技术

为什么hashmap不安全的线程

时间:2023-03-08 21:21:44 网络应用技术

  这是“ Java程序员高级路”专栏的第58。让我们谈谈为什么哈希图不安全。

  众所周知,hashmap通过拉链方法解决了哈希冲突,也就是说,当哈希冲突时,相同哈希值的密钥值将存储在链接列表的形式中。

  在JDK 7上,插入头的方法用于存储链接列表,也就是说,下一个冲突的钥匙值对将放置在上一个键值的前面(放置了同一位置的新元素在链接的头列表的头上。为了扩展,它可能导致链接列表,从而导致死周期。

  调整方法源代码:

  转移方法用于将小数阵列的元素传输和复制到新数组。

  请注意两行代码,同一位置的新元素将放在链接列表的头部。

  如果是这样,则在扩展之前。

  因此,在正常扩展之后,这是以下内容。

  假设有两个线程可以同时扩展,则执行线程A被悬挂。目前,线程A:E = 3,Next = 7,e.next = null

  线程B开始执行并完成数据传输。

  目前,下一个为3、3。

  随后,螺纹A获得的CPU时间胶片继续执行,将3位在与新数组相对应的相应位置中,并且在本轮周期后的线程A的情况如下执行:

  执行下一轮周期。目前,E = 7,原始线程A中的原始7为5,但是由于表由线程A和线程B共享,并且在成功执行线程B之后,7中的7中的7个变为3.线程A此时,7的侧面也为3。

  插入头的方法已成为以下内容:

  似乎没有问题,此时接下来= 3,e = 3。

  在下一轮周期中,此时,由于线B已将下一个螺纹转为NULL,因此这一轮周期应该是最后一轮。

  接下来,在执行为3.ext = 7之后,3和7相互链接。执行完成后,将3重新插入链接列表中。执行结果如下图所示:

  在娃娃的开头,元素5变成了遗弃的婴儿,悲惨的~~~

  但是,该问题已在JDK 8上修复,链接列表的原始顺序将在扩展过程中保持,指的是哈希图容量扩展机制。

  在正常情况下,当哈希冲突发生时,hashmap就是这样:

  但是,当同时执行多线程PUT操作时,如果计算出的索引位置相同,则会导致后一个键覆盖以前的键,这将导致元素损失。

  放置源代码:

  问题发生在步骤②这里:

  两个线程都执行if语句,假设线程A首先执行,则表就是这样:

  然后,执行线程B,然后表就是这样:

  3被杀。

  当线程A执行PUT时,扩展会扩展,因为元素的数量超过了阈值。此时执行可能会导致此问题。

  注意调整大小源代码:

  执行线程A后,线程B中的表也已更改。当然,当要获得时,当然,由于元素尚未转移,因此它会变为零。

  为了促进每个人更加系统地了解Java,第二个兄弟向Github打开了“ Java程序员高级路”专栏。您只需要轻轻地与所有朋友一起扮演怪物,以升级正确的权利。

  github地址:https://github.com/itwanger/tobebetterjavaer