ConcurrentHahMap 基于源码解析

ConcurrentHashMap源码解析,多线程扩容 前面一篇已经介绍过了 HashMap 的源码: HashMap并不是线程安全的,他就一个普通的容器,没有做相关的同步处理,因此线程不安全主要体现在: put、get 等等核心方法在多线程情况下,都会出现修改的覆盖,数据不一致等等问题。比如多个线程 put 先后的问题,会导致结果覆盖,如果一个 put 一个get,也可能会因为调度问题获取到错误的结果; 多线程操作有读有写的时候,可能会出现一个典型异常:ConcurrentModificationException 另外扩容的时候,hashmap1.7 的实 阅读详情

目录

1、简单总结

2、JDK1.7 segments + HashEntry数组 + 链表解析

3、JDK1.8 散列表 + 红黑树 + CAS 解析


1、简单总结

  • JDK1.8底层是散列表+红黑树、JDK1.7底层是segments + HashEntry数组;
  • ConCurrentHashMap支持高并发的访问和更新,它是线程安全的;
  • 检索操作不用加锁,get方法是非阻塞的;
  • key和value都不允许为null

2、JDK1.7 segments + HashEntry数组 + 链表解析

参考:https://zhuanlan.zhihu.com/p/49754357

如下图所示,segments继承了可重入锁ReentrantLock,每个片段有一个锁,叫做“分段锁”。

1).Segment(分段锁)

ConcurrentHashMap中的分段锁称为Segment,它即类似于HashMap的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表,同时又是一个ReentrantLock(Segment继承了ReentrantLock)。

2).内部结构

ConcurrentHashMap使用分段锁技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问,能够实现真正的并发访问。如下图是ConcurrentHashMap的内部结构图:

 

 

从上面的结构我们可以了解到,ConcurrentHashMap定位一个元素的过程需要进行两次Hash操作。

第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部。

3).该结构的优劣势

坏处

这一种结构的带来的副作用是Hash的过程要比普通的HashMap要长

好处

写操作的时候可以只对元素所在的Segment进行加锁即可,不会影响到其他的Segment,这样,在最理想的情况下,ConcurrentHashMap可以最高同时支持Segment数量大小的写操作(刚好这些写操作都非常平均地分布在所有的Segment上)。

所以,通过这一种结构,ConcurrentHashMap的并发能力可以大大的提高。


3、JDK1.8 散列表 + 红黑树 + CAS 解析

参考:https://zhuanlan.zhihu.com/p/35668936

JDK8中ConcurrentHashMap参考了JDK8 HashMap的实现,采用了数组+链表+红黑树的实现方式来设计,内部大量采用CAS操作。

CAS:是compare and swap的缩写,即我们所说的比较交换。CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行。

Node:JDK8中彻底放弃了Segment转而采用的是Node(保存key,value及key的hash值的数据结构。其中value和next都用volatile修饰,保证并发的可见性。),其设计思想也不再是JDK1.7中的分段锁思想。

class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; volatile V val; volatile Node<K,V> next; //... 省略部分代码} </strong>

红黑树:在JDK8中ConcurrentHashMap的结构,由于引入了红黑树,使得ConcurrentHashMap的实现非常复杂,我们都知道,红黑树是一种性能非常好的二叉查找树,其查找性能为O(logN),但是其实现过程也非常复杂,而且可读性也非常差。

总结:

JDK1.8版本中synchronized+CAS+HashEntry+红黑树:

  • 数据结构:取消了Segment分段锁的数据结构,取而代之的是数组+链表+红黑树的结构。
  • 保证线程安全机制:JDK1.7采用segment的分段锁机制实现线程安全,其中segment继承自ReentrantLock。JDK1.8采用CAS+Synchronized保证线程安全。
  • 锁的粒度:原来是对需要进行数据操作的Segment加锁,现调整为对每个数组元素加锁(Node)。
  • 链表转化为红黑树:定位结点的hash算法简化会带来弊端,Hash冲突加剧,因此在链表节点数量大于8时,会将链表转化为红黑树进行存储。
  • 查询时间复杂度:从原来的遍历链表O(n),变成遍历红黑树O(logN)。

 

 

ConcurrentHashMap源码解析 JDK8 一、简介 上篇文章详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理。 首先在看本文之前,希望对HashMap有一个详细的了解。不然看直接看ConcurrentHashMap的源码还是有些费劲的。 相信对HashMap,HashTable有一定了解,应该知道HashMap是不具备线程安全性的,在resize时会丢数据(JDK8),而HashTa... 阅读详情

相关推荐

weblogic 集群搭建,双机部署,相关问题记录

4.5.集群搭建1 参考网址https://wenku.baidu.com/view/76365129cd1755270722192e453610661ed95aa4.html IP地址 端口 角色 192.168.1.160 9001 AdminServer ...

zl386119974的专栏 1670

ConcurrentHashMap源码解析(看这一篇就够了,超简约且详细)

作者 Doug Lea 本身对这个问题有过回答,在并发编程中,null 值容易引来歧义, 假如先调用 get(key) 返回的结果是 null,那么我们无法确认是因为当时这个 key 对应的 value 本身放的就是 null,还是说这个 key 值根本不存在,这会引起歧义,如果在非并发编程中,可以进一步通过调用 containsKey 方法来进行判断,但是并发编程中无法保证两个方法之间没有其他线程来修改 key 值,所以就直接禁止了 null 值的存在。返回的时候n+1,有返回了当前值。

Nuan_Feng的博客 1611

别再瞎调了!STM32 Systick延时函数避坑指南(正点原子、野火、慧净代码对比)

本文深入解析STM32 Systick延时函数的实现差异与优化策略,对比正点原子、野火、慧净等主流方案的优缺点。针对us和ms级延时精度问题,提供避坑指南和高级优化技巧,帮助开发者根据项目需求选择最佳方案,提升嵌入式系统的定时控制精度。

weixin_28717807的博客 340

HashMap源码解析

读完这一篇HashMap,吊打面试

String0715的博客 1651

【Linux系统】Kdenlive软件多机位同音频视频同步化处理

Kdenlive简介 官网链接:https://kdenlive.org/zh/ 命令行安装: apt-get install kdenlive Kdenlive能够进行多轨道视频编辑,可以使用和调整多条音频、视频轨道。每条轨道可以按需进行单独锁定、静音。 Kdenlive多机位同音频视频同步化处理步骤 1. 新建Kdenlive文件 选择<文件>-<新建>,建立新的kdenlive文件,初始设置为<视频轨:2>,<音频轨:2>。 视.

qq_31550269的博客 1886

SpringBoot整合海康SDK实战:从设备初始化到PS流录像转MP4全流程(附避坑指南)

本文详细介绍了SpringBoot整合海康SDK的完整实战流程,涵盖设备初始化、通道管理、录像检索与下载。针对海康设备生成的PS流录像文件无法直接播放的痛点,重点解析了如何利用FFmpeg高效、无损地将其转换为通用的MP4格式,并提供了关键的避坑指南和性能优化建议。

chair的专栏 764

并发编程源码解析(九)CyclicBarrier源码解析

CyclicBarrier一般被称作栅栏,这是一个很形象的称呼,它的作用很神奇,它是等待n个线程到达之后在一起执行。影响一点解释就是如果用羊形容线程的话,它就像是一个栅栏,我们给这个栅栏最大容量设置为3,那么当栅栏进入第一只和第二只羊的时候一定要三只羊全进入时才可以同时执行。使用的场景比较少,我的理解是需要等待前三个线程都跑出结果的情况才会使用到,也许在算法的一些场景会有这个情况。CyclicBarrier不同于我们之前学到的很多类是继承AQS,它的内部是直接使用ReentrantLock来实现。

qq_33781946的博客 994

YOLOv8【第十一章:视频追踪与流处理篇·第6节】BoT-SORT 改进:结合相机运动补偿(CMC)提升追踪稳定性!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 718

ConcurrentHashMap Put方法源码解析

废话不多说,直接开整! 当调用ConcurrentHashMap的put方法时,其实就是间接调用putVal(key, value, false), false所对应的参数为OnlyIfAbsent,表面语义指“只有不存在的时候”。当置false指无论key在表中所对应的值是否存在,都使用value进行更新 public V put(K key, V value) { return putVal(key, value, false); } 下面为putVal的源码,之

qq_40244364的博客 948

手把手教你学Simulink--基于飞轮储能系统的场景实例:飞轮储能与锂电池混合储能系统的协同控制

本文详细介绍了基于Simulink的飞轮储能与锂电池混合储能系统协同控制建模方法。通过高通/低通滤波器实现功率分配,使飞轮处理高频波动(±100kW),锂电池承担削峰填谷(50kW)。仿真结果表明,该系统效率达88%,锂电池循环次数减少90%,投资成本比纯电池方案节省200万美元。文章包含完整的建模步骤、控制策略设计和多场景仿真分析,为构建高效、长寿、经济的智能储能系统提供了实用解决方案。

MHD0815的博客 342

3、无限维系统理论中的算子与半群:概念、定理及应用

本博文深入探讨了无限维系统理论中的两个核心概念:里茨谱算子与卢默-菲利普斯定理。文章首先介绍了里茨基的定义与性质,分析了谱、预解集及特征值在无限维系统中的特性,并详细阐述了里茨谱算子的条件及其生成C0-半群的能力,结合阻尼欧拉-伯努利梁模型展示了其应用。随后,文章介绍了卢默-菲利普斯定理及其推论,通过多个偏微分方程实例(如一阶方程、柔性梁、波动方程和扩散问题)说明如何利用该定理判断算子是否生成压缩半群。此外,还强调了状态空间选择和边界条件对系统适定性的重要影响,并总结了相关问题的解决步骤与方法。

flink9streamer的博客 148

并发编程源码解析(七)CountDownLatch 源码解析

CountDownLatch一般来说我们会称为计数器,是Java并发编程中的一个工具类,它可以帮助控制多个线程间的同步,使得某个线程在等待另外一组线程完成某些操作后再继续执行。 具体来说,CountDownLatch中包含一个初始值,其它线程可以通过调用这个对象的countDown()方法来减小这个值,而某个线程可以通过调用这个对象的await()方法来等待这个值减小到0。当这个值减小到0时,await()方法将返回,表示其它线程已经完成了某些操作,可以继续执行。 但是 CountDownLatch 只

qq_33781946的博客 916

【CanMV K210】AI 视觉 MNIST 手写数字识别与分类推理

本文介绍了基于CanMV K210开发板的MNIST手写数字识别实验。实验通过摄像头采集图像,经过开窗、灰度化、缩放、反色等预处理后,使用KPU神经网络加速器运行MNIST分类模型,最终在LCD上显示识别结果。重点讲解了分类模型与检测模型的区别、图像预处理流程以及KPU推理结果的解析方法。实验帮助理解从图像采集到分类输出的完整AI视觉处理链路,并提供了调试思路和硬件连接说明。

Mr数据杨 366

并发编程源码解析(六)ConcurrentHashMap源码解析之三并发扩容

首先,我们先来复习一下sizeCtl的状态,-1 正常初始化< -1 是正在扩容0 没有初始化> 0 数组扩容阈值/ 没有初始化是代表初始化长度接着我们来介绍一下关于并发扩容的基本概念,的第一个线程进入线程之后会将sizeCtl设置为 -2,然后将新的数组创建好,并将扩容任务拆分成若干个子任务,当其他线程进行put时,如果检测到了正在扩容就会将 sizeCtl +1 (会变成-3) 以表示新的线程参与并发扩容;

qq_33781946的博客 2181

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

ConcurrentHashMap 源码解析合集

在学习ConcurrentHashMap之前还需要弄懂 CAS 和 LongAdder这两个东西。相信如果把下面六篇文章看完,你对ConcurrentHashMap就会有进一步的了解。看完上面两篇前置内容,下面的内容学习起来会更清楚些。希望大家一起学习,一起进步!...

一起加油!!! 166

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java集合—— ConcurrentHashmap源码解析

基于JDK 8解析常用集合——ConcurrentHashmap,从源码入手分操作一步一步了解原理,简单易懂,怎样保证线程安全的? 通过了哪些手段保证了性能?扩容同时删除或者查询有影响吗?

共勉 895

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

ConcurrentHashMap源码解析(jdk1.7)

一、底层结构 二、源码解析 1.HashEntry数据结构 static final class HashEntry<K,V> { final int hash; final K key; //保证数据可见性,即保证每次get到的数据都是最新的 volatile V value; volatil...

PANDA博客 373

HashTable源码解析

HashTable源码解析 转载出处:blog.youkuaiyun.com/android_jia… Hashtable与HashMap有哪些区别? 1.关于null,HashMap允许key和value都可以为null,而Hashtable则不接受key为null或value为null的键值对。 2.关于线程安全,HashMap是线程不安全的,Hashtable是线程安全的,因为Hashtable的许多操...

方兴未艾 470

Map源码解析之ConcurrentHashMap(JDK1.7)

Map源码解析之HashMap Map源码解析之HashMap红黑树 Map源码解析之HashMap补充:集合、迭代器、compute、merge、replace Map源码解析之LinkedHashMap Map源码解析之TreeMap Map源码解析之HashTable Map源码解析之ConcurrentHashMap(JDK1.8)(一) Map源码解析之ConcurrentHashMa...

翻身已碰头的博客 537

JUC源码解析文章目录

基础知识: 原子操作的实现:CAS与锁 JMM与happens-before Synchronized ThreadLocal 同步器 J.U.C之基——AQS 锁 ReentrantLock Condition CountDownLatch Semaphore CyclicBarrier ReentrantReadWriteLock 并发容器 CopyOnWriteArrayList Conc...

业精于勤荒于嬉 行成于思毁于随 2092

IOC源码解析(1)

通过registerBeanDefinitions方法解析和注册bean,进入registerBeanDefinitions方法中。进入this.beanFactory.getBeanDefinition(beanName)方法中,会发现。进入this.loadBeanDefinitions((Resource)resource)进入this.getRegistry().getBeanDefinitionCount()中。进入this.loadBeanDefinitions(location)中。

weixin_42592415的博客 540

ConcurrentHashMap 核心源码的基本解析

ConcurrentHashMap 的数据结构

huhan123456789的博客 291

3W字详细解析 ConcurrentHashMap 1.7和1.8源码,再也不用担心被面试官吊打了。

前言 上篇文章介绍了 HashMap 源码后,在博客平台广受好评,让本来己经不打算更新这个系列的我,仿佛被打了一顿鸡血。真的,被读者认可的感觉,就是这么奇妙。 然后,有读者希望我能出一版 ConcurrentHashMap 的解析。所以,今天的这篇文章,我准备讲述一下 ConcurrentHashMap 分别在JDK1.7和 JDK1.8 的源码。文章较长,建议小伙伴们可以先收藏再看哦~ 说一下...

烟雨星空的博客 3620

JDK1.8源码解析之ConcurrentHashMap

ConcurrentHashMap源码解析概述目录结构put方法putAlladdCounthelpTransfertryPresizetransfersize如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出...

m0_37148920的博客 630

ConcurrentHashMap源码解析(JDK1.8)

目录 ConcurrentHashMap源码解析 一、什么是ConcurrentHashMap 二、源码解析 1.构造函数及部分参数 2.初始化 3.put操作 4.get操作 5.remove操作 6.clear操作 ConcurrentHashMap源码解析 一、什么是ConcurrentHashMap ConcurrentHashMap与HashMap数据结构一致,他是线程安全的。 ConcurrentHashMap中是不允许key和value为null的,而HashMap是

Me_xuan的博客 744

源码解析——HashMap

上面讲了一大堆理论,先来实践一下吧。HashMap为什么要用数组+链表/红黑树的结构?这个比较简单,数组+链表/红黑树(注意区别JDK1.7和1.8)HashMap为什么要用数组+链表/红黑树的结构?为了提高HashMap的查询效率和空间利用率数组是一种连续的存储结构,它可以通过索引快速定位元素,但是它的长度是固定的,如果数组过大,会浪费空间;如果数组过小,会导致哈希冲突。链表是一种离散的存储结构,它可以动态地增加或删除元素,但是它需要遍历才能找到元素,如果链表过长,会降低查询效率。

小熊的学习记录 607
上一篇: java 日常醒脑
下一篇: Spring事务管理接口 + 实例
Longtermevolution
博客等级 码龄9年 113粉丝 249原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值