前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解析为什么hashmap是线程不安全的?「建议收藏」

解析为什么hashmap是线程不安全的?「建议收藏」

作者头像
全栈程序员站长
发布2022-11-10 15:28:24
2450
发布2022-11-10 15:28:24
举报
文章被收录于专栏:全栈程序员必看
  1. 扩容

一般我们声明HashMap时,使用的都是默认的构造方法:HashMap<K,V>,看了代码你会发现,它还有其它的构造方法:

HashMap(int initialCapacity, float loadFactor),

其中参数initialCapacity为初始容量,loadFactor为加载因子,扩容就是在put加入元素的个数超过initialCapacity * loadFactor的时候就会将内部Entry数组大小扩大至原来的2倍,然后将数组元素按照新的数组大小重新计算索引,放在新的数组中,同时修改每个节点的链表关系(主要是next和节点在链表中的位置)。

假设这里有两个线程同时执行了put()操作,并进入了transfer()环节:

解析为什么hashmap是线程不安全的?「建议收藏」
解析为什么hashmap是线程不安全的?「建议收藏」

刚开始:

线程1中的e指向key(0),next指向key(4),此时线程1挂起。

解析为什么hashmap是线程不安全的?「建议收藏」
解析为什么hashmap是线程不安全的?「建议收藏」

线程2调度完成所有节点的移动,移动后结果为:

解析为什么hashmap是线程不安全的?「建议收藏」
解析为什么hashmap是线程不安全的?「建议收藏」

线程1继续执行,线程一会把线程二的新表当成原始的hash表,将原来e指向的key(0)节点当成是线程二中的key(0),放在自己所建table[0]的头节点。注意线程1的next仍然指向key(4),

虽然此时key(0)的next已经是null。

解析为什么hashmap是线程不安全的?「建议收藏」
解析为什么hashmap是线程不安全的?「建议收藏」
  1. 执行e.next = newTable[i],于是 key(0)的 next 指向了线程1的新 Hash 表,因为新 Hash 表为空,所以e.next = null,
  2. 执行newTable[i] = e,所以线程1的新 Hash 表第一个元素指向了线程2新 Hash 表的 key(0)。好了,e 处理完毕。
  3. 执行e = next,将 e 指向 next,所以新的 e 是 key(4)

线程1的e指向了上一次循环的next,也就是key(4),此时key(4)的next已经是key(0)。将key(4)插入到table[0]的头节点,并且将key(4)的next设置为key(0)。此时仍然没有问题。

解析为什么hashmap是线程不安全的?「建议收藏」
解析为什么hashmap是线程不安全的?「建议收藏」
  1. 现在的 e 节点是 key(4),首先执行Entry<K,V> next = e.next,那么 next 就是 key(0)了
  2. 执行e.next = newTable[i],于是key(0) 的 next 就成了 key(4)
  3. 执行newTable[i] = e,那么线程1的新 Hash 表第一个元素变成了 key(4)
  4. 执行e = next,将 e 指向 next,所以新的 e 是 key(0)
解析为什么hashmap是线程不安全的?「建议收藏」
解析为什么hashmap是线程不安全的?「建议收藏」
  1. 现在的 e 节点是 key(0),首先执行Entry<K,V> next = e.next,那么 next 就是 null
  2. 执行e.next = newTable[i],于是key(0) 的 next 就成了 key(4)
  3. 执行newTable[i] = e,那么线程1的新 Hash 表第一个元素变成了 key(0)
  4. 执行e = next,将 e 指向 next,所以新的 e 是 key(4)

总结版:HashMap在put的时候,插入的元素超过了容量(由负载因子决定)的范围就会触发扩容操作,就是rehash,这个会重新将原数组的内容重新hash到新的扩容数组中,在多线程的环境下,存在同时其他的元素也在进行put操作,如果hash值相同,可能出现同时在同一数组下用链表表示,造成闭环,导致在get时会出现死循环,所以HashMap是线程不安全的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/183168.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月11日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档