在知乎上看到的,觉得说的很清楚,所以就转载过来做一下记录。具体的出处可以看图片的水印。
首先看下HashMap的工作原理,我们回顾一下HashMap的结构:

HashMap的结构就是哈希表,底层是一个数组,这个数组中尽可能地分散所有的key,通过key的hash值得到数组下标,然后把entry插到该数组,假如有两个不同的key被分到相同的下标,也就是哈希冲突,那么该数组在该下标下就会形成链表。

为了减少冲突,我们需要时刻留意当前的size是否太大,检查是否需要扩容,一旦超过设定的threshold,那么就要重新增大数组尺寸,此时所有元素都需要重新计算应该放置的下标。

扩容、rehash

上面为扩容的方法,可以看到,实际上扩容就是新建了一个数组,同时调用了transfer方法,给新数组赋值后覆盖掉原来的table。那我们来看看transfer里面发生了什么:

从代码上可以看出,原来链表的元素有可能已经不在原来的数组上,也就是元素都被重新排到数组上了。

图解rehash

扩容前的结构:

在transfer方法中,对原来的table进行遍历重排序,我们来模拟一下这个过程。重新排序的关键在于,数组长度变了以后,重新计算得出的下标,这与哈希算法有关,为了便于理解,我们简单地认为本HashMap的哈希算法为用key 去mod数组的长度,这也是理解transfer如何重新排列链表的关键。

这是第一次循环后的结果:

第二步:

继续遍历,最终结果如下

以上就是在单线程下,重新排列后的链表。

多线程下的rehash

我们从上文看到,单线程下的rehash是完全没有问题的,那么在多线程下会出现什么问题呢?我们仍然用清晰明了的图来做演示

首先,我们假设有两个进程同时进行put操作,且让HashMap进行扩容,同时进入transfer方法

此时的状态如下:

然后线程2完成了transfer方法,如下

此时,又回到线程1,但此时,完成第一次循环过程:

继续进行下一次循环:

然后e = next = key(3),再继续下一次循环:

当执行完:

e.next = newTable[3];

newTable[3] = e;

时,至此,循环链表形成了。

另外大家也可以看小灰漫画中的一篇文章,写的也很清楚:
https://mp.weixin.qq.com/s?__biz=MzI2NjA3NTc4Ng==&mid=2652079766&idx=1&sn=879783e0b0ebf11bf1a5767933d4e61f&chksm=f1748d73c6030465fe6b9b3fa7fc816d4704c91bfe46cb287aefccee459153d3287172d91d23&scene=21#wechat_redirect

并发下HashMap为什么不是线程安全的?相关推荐

  1. ArrayList、HashMap、HashSet是线程不安全的,高并发下如何解决?

    1.故障现象 :ArrayList的add()方法并没有使用synchronized所以是线程不安全的,会造成java.util.ConcurrentmodificationException(并发修 ...

  2. 并发下HashMap头插会造成死循环情况说明

    说明: JDK1.8之前HashMap触发扩容机制时,会创建新的Entry[ ]数组,将旧的Entry数据进行复制,当某个entry上具有链式结构时,采用头插方式进行数据迁移,即将旧链表数据从头部遍历 ...

  3. 它又来了!C**HashMap是如何保证线程安全的?会用不就完了?

    欢迎关注方志朋的博客,回复"666"获面试宝典 阅读此篇文章,你需要有以下知识基础 Java内存模型,可见性问题 CAS HashMap底层原理 我们知道,在日常开发中使用的Has ...

  4. Java8 HashMap 扩容机制与线程安全分析

    如果大家有仔细阅读过 HashMap 的源码就会发现 HashMap 的哈希表初始化并不是在其构造函数中进行的,而是 resize() 方法. 这篇文章不对 HashMap 中的树进行介绍. 一.Ha ...

  5. 面试官问你HashMap底层你用线程安全吊打他

    面试中,HashMap可以说是必问的,既然这样,我们应该怎么准备怎么回答呢,看看这篇文章,估计你会懂点东西. 先看看这两张图,是其内部的存储结构 说起HashMap,我们可以先从底层实现说起,Hash ...

  6. 2020年Android面试题整理

    一.Android四大组件 1.Android设计模式有哪些?什么是代理模式,工厂模式?简单工厂模式和抽象工厂模式的区别? 单例模式: 书写单例模式代码.单例的实现方式很多,比如懒汉式.饿汉式.静态内 ...

  7. HashMap 在并发下可能出现的问题分析!

    我们都知道,HashMap在并发环境下使用可能出现问题,但是具体表现,以及为什么出现并发问题,可能并不是所有人都了解 这篇文章记录一下HashMap在多线程环境下可能出现的问题以及如何避免. 在分析H ...

  8. hashmap put复杂度_你碰到过几种HashMap在高并发下出现的问题,哪些可能出现的问题...

    前言: 我们都知道,HashMap在并发环境下使用可能出现问题,但是具体表现,以及为什么出现并发问题, 可能并不是所有人都了解,这篇文章记录一下HashMap在多线程环境下可能出现的问题以及如何避免. ...

  9. HashMap--并发下死循环(HashMap不能在多线程下使用)

    为什么80%的码农都做不了架构师?>>>    在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMa ...

最新文章

  1. # c++运算符重载之 前置++, 后置++, 负号运算符, 类型转换函数, 以及输入输出运算符...
  2. mysql判断条件用法,MySQL数据库讲解条件判断函数 MySQL数据库使用教程
  3. Visio的VBA初探
  4. python中的tab补全功能添加
  5. 关于Scikit-Learn你(也许)不知道的10件事
  6. 几何画板中该如何插入公式
  7. ie11不兼容java_解决ie11不兼容的多个方法
  8. 交通灯控制系统的设计
  9. 英语知识点整理day03
  10. 对视频声音,音频进行音量标准化和响度均化,归一化的标准,原理以及具体操作
  11. JavaScript学习笔记 06、DOM元素—③定时器与延时器
  12. java变量无法解析出现的原因_不明白为什么这个变量无法解析为一个类型? (JAVA)...
  13. mysql 按月 季度 统计数据
  14. 程序员经典电子书下载(超全)
  15. 【HTML】动画合集--跟着pink老师学习
  16. 电子元器件篇---二极管
  17. UI设计师ps的使用,产品经理
  18. 协同过滤(Collaborative Filtering):UserCF and Item CF
  19. 数据交易思享会 | 美创科技分享《数据交易准入安全》
  20. 我开发了一个下载器 带宽拉满

热门文章

  1. 解决svn上传文件出现二进制相关不能对比文本差异
  2. python 读取.nii格式图像
  3. 路还很长!有一个人陪让我不惧任何
  4. Windows XP中如何自动终止Blackice防火墙(转)
  5. 食住玩CR疯狂渲染大师|3dmax效果图大师们怎么用CORONA设置CR成品效果大图的渲染参数?3dmax千千问为什么?
  6. 学习Nginx这一篇就够了
  7. 男性≈机器?男性号≈僵尸号?,王思聪的抽奖撕开了微博算法猫腻
  8. win8/8.1改win7原版系统全部教程之PE装微软原版ISO文件的系统(3)
  9. STM32笔记 (六)利用ST-Link进行Debug调试
  10. Exchange Online功能介绍