最近在学习有关于Java的基础知识,在学习到HashMap的相关知识的时候,了解了HashMap的并发中会出现的问题,在此记录,加深理解(这篇文章是基于Java1.7的,主要是为了更加直观,更新版本的代码更加复杂,等理解后会继续总结).

  HashMap的内部存在一个数组,每个位置存放一个自定义的Node对象,Node对象中存在下一个对象的引用,类似如下结构

    

  每次添加后size属性都会增加,当size属性超过了阈值(表现为大于threshold属性的值)时,会触发resize(itn size)方法,进行扩容,扩容的方式是创建一个2倍大的新的数组,对老transfer()函数,对数组进行遍历重算新hash,并赋值到新数组中,如果程序是并发执行,就容易出现问题.

  核心代码如下:

     /**
* Transfers all entries from current table to newTable.
*/
void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
src[j] = null;
do {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}
}

  简单来说就是取一个节点,循环找下一个,赋到新的数组中,如果多线程就会出现问题

  如果线程a准备扩容,发生线程切换时正好处于这个状态(只是示意图,大小等并不符合真实情况)

  

  此时线程切换,线程b完成了扩容的过程,再切回线程a,此时扩容完成,但是线程a依旧执行,变量仍然指向那些节点,此时如果出现以下情况

  

  此时继续执行,执行了e.next = newTable[i]; newTable[i] = e; e = next;此时就会出现循环列表

  

  此时循环链表出现,当我们调用get()方法,hash在位置,且寻找元素不存在的时候,就会进入死循环无法跳出.

  原理的简单描述就是这样,如果需要在并发条件下使用,可以使用Java并发包中的ConcurrentHashMap.

  

通过源码理解HashMap的并发问题的更多相关文章

  1. 通过源码理解Spring中@Scheduled的实现原理并且实现调度任务动态装载

    前提 最近的新项目和数据同步相关,有定时调度的需求.之前一直有使用过Quartz.XXL-Job.Easy Scheduler等调度框架,后来越发觉得这些框架太重量级了,于是想到了Spring内置的S ...

  2. 通过源码理解UST(用户栈回溯)

    UST原理:如果gflags标志中包含了UST标志,堆管理器会为当前进程分配一块内存,这个内存区域就是UST数据库(user-mode stack trace database),并建立一个STACK ...

  3. 通过源码了解ASP.NET MVC 几种Filter的执行过程

    一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多人觉得平时根本不需要知道这些,会用就行了.其实阅读源 ...

  4. Linux下通过源码编译安装程序

    本文简单的记录了下,在linux下如何通过源码安装程序,以及相关的知识.(大神勿喷^_^) 一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件: ...

  5. 通过源码了解ASP.NET MVC 几种Filter的执行过程 在Winform中菜单动态添加“最近使用文件”

    通过源码了解ASP.NET MVC 几种Filter的执行过程   一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神 ...

  6. 在centos6.7通过源码安装python3.6.7报错“zipimport.ZipImportError: can't decompress data; zlib not available”

    在centos6.7通过源码安装python3.6.7报错: zipimport.ZipImportError: can't decompress data; zlib not available 从 ...

  7. Kafka详解六:Kafka如何通过源码实现监控

    问题导读: 1.kafka的消费者组的消费偏移存储,kafka支持两个版本?        2.ConsumerOffsetChecker类的作用是什么?        3.Kafka如何通过源码实现 ...

  8. 通过源码编译安装VIM

    开发中使用的是Ubuntu 12.04 LTS,通过sudo apt-get install vim安装的版本较低,不支持YCM,所以,用源码编译并安装最新的Vim. 卸载旧版本的Vim: sudo ...

  9. echarts 通过源码方法 传入对应data数据获取分割步长值

    通过源码方法获取这里的分割数字长度 /** * Quantity of a number. e.g. 0.1, 1, 10, 100 * * @param {number} val * @return ...

随机推荐

  1. 五十四、linux 编程——TCP 编程模型

    54.1 编程模型介绍 54.1.1 TCP 客户端服务器编程模型 客户端调用序列 调用 socket 函数创建套接字 调用 connect 连接服务器端 调用 I/O 函数(read/write) ...

  2. mysql的order by注入

    最近在做一些漏洞盒子后台项目的总结,在盒子众多众测项目中,注入类的漏洞占比一直较大.其中Order By注入型的漏洞也占挺大一部分比例,这类漏洞也是白帽子乐意提交的类型(奖金高.被过滤概览小).今天给 ...

  3. python excel写入及追加写入

    # -*- coding:utf-8 _*- """ @author:Administrator @file: excel.py Description :如果行数是10 ...

  4. 怎样解决canvas 插件 和html 页面中的事件冲突问题 ?

    很简单 ,在html 执行事件所在的div中 设置 position:relative;    

  5. Java SE之快速失败(Fast-Fail)与快速安全(Fast-Safe)的区别[集合与多线程/增强For](彻底详解)

    声明 特点:基于JDK源码进行分析. 研究费时费力,如需转载或摘要,请显著处注明出处,以尊重劳动研究成果:博客园 - https://www.cnblogs.com/johnnyzen/p/10547 ...

  6. window10:jdk 8下载和安装步骤

    window10:jdk 8下载和安装步骤 点击链接:https://blog.csdn.net/qq_39720249/article/details/80721719

  7. Spring Cloud 2.x-前言

    Spring Cloud Spring Boot  简介 模块介绍 文章列表 简介 微服务已经成为企业开发的标配,阿里的Dubbo已经被企业大规模使用,Spring Cloud作为后起之秀,同时也是 ...

  8. tensorflow调试tfdbg

    tensorflow调试工具:tfdbg 使用教程:https://www.cnblogs.com/hellcat/articles/7812119.html 遇到的错误信息及解决方案 ModuleN ...

  9. linux下c通过虚拟地址映射读写文件的代码

    在代码过程中中,把开发过程中比较好的一些代码片段记录起来,如下的代码内容是关于 linux下c通过虚拟地址映射读写文件的代码,应该对小伙伴有些好处.#include<stdio.h>#in ...

  10. openpyxl使用sheet.rows或sheet.columns报TypeError: 'generator' object is not subscriptable解决方式

    解决方案: 因为新版本的openpyxl使用rows或者columns返回一个生成器所以可以使用List来解决报错问题 >>> sheet.columns[0] Traceback ...