小谈HashMap与ConcurrentHashMap

2023-10-26

HashMap

JDK7:

在JDK7中,HashMap通过数组加链表的形式存储,当元素个数达到阈值,并且数组下标已经存在元素,则会进行扩容,如果数组下标不存在元素,则直接添加,不会扩容。

JDK7中添加元素使用的是头插法,在高并发的环境下可能会导致死链。

新增对象丢失原因:

  • 并发赋值时被覆盖。
  • 扩容中的数据迁移,新增的数据落在了原来的HashMap中,并且所在的哈希槽已经被遍历过。
  • 多个线程同时执行resize方法,每个线程都会创建Entry,最后的赋值中会覆盖其他线程的数据。
  • 迁移丢失。在并发迁移过程中,next被提前设置为null。

JDK8:

在JDK8中,HashMap通过数组加链表或红黑树的节后进行存储。当链表的长度大于等于8(8来自于泊松分布),并且哈希槽的个数不小于64的时候才会进行链表转红黑树,如果链表大于等于8,但是哈希槽小于64,则会执行resize方法进行扩容。当红黑树节点小于等于6的时候,红黑树会退化成链表。

默认容量为16,默认负载因子是0.75,所以当节点个数大于16 * 0.75 = 12时就需要扩容。

JDK8中添加数据采用的尾插法,避免了死链还保证了数据有序性,同时统计了链表的长度,方便树化和链表化。

ConcurrentHashMap

JDK7:

在JDK7中ConcurrentHashMap是由Segment[]数组加上HashEntry[]组成的。底层用的数组加链表。

原理上ConcurrentHashMap采用的是分段锁,其中的Segment继承于ReentrantLock,它的锁粒度比HashTable更细,当一个线程来访问时,只会占用对应的Segment,对其他Segment不想影响。

在进行put时,通过scanAndLockForPut方法获取到锁,首先通过自旋尝试获取锁,当自旋次数达到MAX_SCAN_RETRIES时,会强行上锁获取对象。

get逻辑比较简单,因为Entry的value属性都是通过volatile修饰的,可以保证可见性,所以不需要加锁。

JDK8:

JDK8抛弃了原有的分段锁,使用的是CAS + synchronized

在putVal时,当该table[i]为空时,直接通过cas进行put;当table[i]不为空,并且table[i]的hash值是-1时,表示其他线程正在扩容,调用helpTransfer()帮助一起扩容;当table[i]有值,且没有在扩容时,直接通过synchronized锁住哈希槽进行添加。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小谈HashMap与ConcurrentHashMap 的相关文章

随机推荐

  • 锁与事务的关系

    在并发场景下 我们往往需要在事务方法中加锁来应对并发 如下 下面以 ReentrantLock 为例子 public final static ReentrantLock MY LOCK new ReentrantLock Transact
  • ubuntu安装ssh无法连接解决日志(已解决,可连接)

    原文链接http bbs chinaunix net thread 3585704 1 1 html 网上有很多介绍在Ubuntu下开启SSH服务的文章 但大多数介绍的方法测试后都不太理想 均不能实现远程登录到Ubuntu上 最后分析原因是
  • SpringBoot项目配置全局处理异常

    1 自定义异常 自定义异常 public class RRException extends RuntimeException private static final long serialVersionUID 1L private St
  • k8s学习

    主节点配置一定要好 K8S学习之路 1 介绍 1 1单机部署 1 2 虚拟化部署 类似window上安装多个linux虚拟机 在虚拟机中部署程序 使得程序之间不会互相影响 1 3 容器化部署 共享了操作系统 保证每个系统拥有自己的文件系统
  • MySQL-binlog2sql:非主从关系实现数据的【数据同步+数据恢复+数据追踪】

    文章目录 MySQL binlog2sql 非主从实时同步 恢复误删数据 1 引 1 介绍 2 功能 3 针对3种场景 4 脚本汇总说明 2 先决条件 1 安装 MySQL 2 修改 MySQL 配置 3 安装 binlog2sql 1 解
  • yii2 mysql设置时区

    第一步 修改配置文件 common config db php 注 8 00为北京时间 Asia Shanghai common config main php 第二步 修改vendor yiisoft yii2 db Connection
  • 抓取网站中的视频

    最近想从别人家的网站宣传片上提取一些素材 借鉴一下 之前也没有弄过 但是我的思路就是从网页的缓存中查找播放完后缓存的视频 然后失败了 然后又想到了网页打开源代码 然后查找到网页源代码饮用的视频的路径 然后找到视频 然后 再次失败 网上找了好
  • css基础———清除浮动的一些方法及区别

    为什么要清楚浮动 地址 http blog csdn net qwe502763576 article details 78811658 清除浮动方法概览 这里例举四种常见的清除浮动方式 方式一 使用overflow属性来清除浮动 ovh
  • 论文阅读

    简介 paper https arxiv org abs 1911 11907 github https github com huawei noah ghostnet Ghostnet CVPR2020 是华为提出的一种轻量级网络 结构类
  • WSL安装

    WSL安装教程 WSL简介 Windows Subsystem for Linux 简称WSL 是一个在Windows10上能够运行原生Linux二进制可执行文件 ELF格式 的兼容层 它是有微软与Canonical公司合作开发 其目标正是
  • 模糊查询与带参数跳转

    一 模糊查询 使用
  • 方法重写(override)原则

    方法的重写 override 两同两小一大原则 1 方法名相同 参数类型相同 2 子类返回类型小于等于父类方法返回类型 3 子类抛出异常小于等于父类方法抛出异常 4 子类访问权限大于等于父类方法访问权限
  • oracle RAC ORA-03113 错误解决

    好久 没有更新博客 太懒了 这咋换工作呢 1 错误现象 数据库 客户端连接不正常 频繁报 ORA 03113 错误 oracle 文档中对这个错误这样解释 ORA 03113 错误就是说连接到数据库的网络中断了 有些错误由于频繁出现 原因复
  • res_company_white_url.py 详解

    res company white url py 主要作用是 在数据库中建立一个表 存放白名单的URL 当我们读取文件时 先判断Referer是否在白名单中 如果不在则自动转到一个图片文件 防止盗链 接下来我们看一下主要代码 class C
  • unexpected keyword argument 'renderer'-DjangoUeditor

    今天在集成DjangoUeditor按照官方的Github集成之后 本以为就可以看到后台了没想到直接报错 render got an unexpected keyword argument renderer 报错93行 boundfield
  • 【QT】——06_带参数的信号(笔记)

    信号重载 说明 信号是可以重载的 相同的名字不同的参数 在发射信号的时候给值 emit musicSignal 100 音乐菜单 主窗口 h 创建一个带参的槽来处理信号 注意槽的参数要与信号一致 void dealMusic2 int QS
  • 《Hadoop学习笔记系列》二.Hadoop分布式文件系统 HDFS

    0 Hadoop分布式文件系统 HDFS HDFS以流式数据访问模式来存储超大文件 运行与商用硬件集群上 1 流式数据访问 HDFS的构建思路 一次写入 多次读取是最高效的访问模式 2 Block数据块 HDFS基本读写单位 类似于磁盘的页
  • STM32的ADC采样与多通道ADC采样

    一 单通道采样 参考资料 STM32库开发实战指南 刘火良 杨森著 原理性质的东西还是少讲 因为上面那本书里面讲解的很详细了 直接来看硬件电路图 这里使用的是3362电位器 10K 即用STM32来测量PB0和GND两端的电压 这样的电路设
  • 一篇明白SQL的执行顺序

    这是一条标准的查询语句 这是我们实际上SQL执行顺序 我们先执行from join来确定表之间的连接关系 得到初步的数据 where对数据进行普通的初步的筛选 group by 分组 各组分别执行having中的普通筛选或者聚合函数筛选 然
  • 小谈HashMap与ConcurrentHashMap

    HashMap JDK7 在JDK7中 HashMap通过数组加链表的形式存储 当元素个数达到阈值 并且数组下标已经存在元素 则会进行扩容 如果数组下标不存在元素 则直接添加 不会扩容 JDK7中添加元素使用的是头插法 在高并发的环境下可能