CurrentHashMap线程安全

并发编程 1:CurrentHashMap如何实现高效地线程安全 今天我从线程安全问题开始,分析为什么要使用,进而分析了 Java 7 和 Java 8 中是如何设计实现的,从源码层面说明白了具体的实现逻辑。其实仔细认真读懂后你会发现其实也不是太难。希望本文让你对面试相关问题轻松的应对,同时作为并发编程技巧对你在日常开发可以有所帮助。 阅读详情
AI摘要

本文详细探讨了ConcurrentHashMap在JDK1.7和1.8中的实现差异,包括其数据结构、线程安全机制及优化策略。1.7版采用Segment+分段锁方式,1.8版则优化为数组+链表+红黑树结构,通过CAS+Synchronized提高并发性能。

HashMap是线程不安全的,因此为了解决线程安全问题,提出了两个类:HashTable和CurrentHashMap。

HashTable相关操作都是对方法加synchronized的大锁,效率比较低。ConcurrentHashMap避免了对全局加锁改成了局部加锁操作,这样就极大地提高了并发环境下的操作速度,由于ConcurrentHashMap在JDK1.7和1.8中的实现非常不同,接下来我们谈谈JDK在1.7和1.8中的区别。

一、1.7版本

在JDK1.7中ConcurrentHashMap采用了数组+Segment+分段锁的方式实现。在数组基础上增加了一层Segment,一个Segment对应数组的一段,这样对某段进行的操作只需要锁住对应段,不影响其他段的操作。其中,Segment继承了ReentrantLock并实现了序列化接口,说明Segment的锁是可重入的。


缺点:
ConcurrentHashMap比HashMap多了一次hash过程,第1次hash定位到Segment,第2次hash定位到HashEntry,然后链表搜索找到指定节点。

优点:
在进行写操作时,只需锁住写元素所在的Segment即可,其他Segment无需加锁,提高了并发读写的效率。

二、1.8版本

在JDK1.7中ConcurrentHashMap,数据结构上,首先整体上是数组+链表+红黑树的结构与HashMap保持一致,其次取消了Segment分段锁的数据结构,取而代之的是Node,Node的value和next都是由volatile关键字进行修饰,可以保证可见性。将细化的粒度从段进一步降低到节点。线程安全实现上,采用CAS+Synchronized替代Segment分段锁。

put过程如下

/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
    if (key == null || value == null) throw new NullPointerException();
   int hash = spread(key.hashCode());
   int binCount = 0;
   for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
       if (tab == null || (n = tab.length) == 0)
            tab = initTable();
       else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            if (casTabAt(tab, i, null,
                        new Node<K,V>(hash, key, value, null)))
                break;                   // no lock when adding to empty bin
       }
        else if ((fh = f.hash) == MOVED)
            tab = helpTransfer(tab, f);
       else {
            V oldVal = null;
           synchronized (f) {
                if (tabAt(tab, i) == f) {
                    if (fh >= 0) {
                        binCount = 1;
                       for (Node<K,V> e = f;; ++binCount) {
                            K ek;
                           if (e.hash == hash &&
                                ((ek = e.key) == key ||
                                 (ek != null && key.equals(ek)))) {
                                oldVal = e.val;
                               if (!onlyIfAbsent)
                                    e.val = value;
                               break;
                           }
                            Node<K,V> pred = e;
                           if ((e = e.next) == null) {
                                pred.next = new Node<K,V>(hash, key,
                                                         value, null);
                               break;
                           }
                        }
                    }
                    else if (f instanceof TreeBin) {
                        Node<K,V> p;
                       binCount = 2;
                       if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
                                                      value)) != null) {
                            oldVal = p.val;
                           if (!onlyIfAbsent)
                                p.val = value;
                       }
                    }
                    else if (f instanceof ReservationNode)
                        throw new IllegalStateException("Recursive update");
               }
            }
           ...
   return null;
}

ConcurrentHashMap会判断tabAt(tab, i = (n - 1) & hash)是不是 null,是的话就直接采用CAS进行插入,而如果不为空的话,则是synchronized锁住当前Node的首节点,这是因为当该Node不为空的时候,证明了此时出现了Hash碰撞,就会涉及到链表的尾节点新增或者红黑树的节点新增以及红黑树的平衡,这些操作自然都是非原子性的。从而导致无法使用CAS,当Node的当前下标为null的时候,由于只是涉及数组的新增,所以用CAS即可。

参考链接:https://baijiahao.baidu.com/s?id=1617089947709260129&wfr=spider&for=pc

Selenium自动化测试遇到shadow-root元素?3种实用解决方案帮你搞定 本文针对Selenium自动化测试中遇到shadow-root元素难以定位的常见问题,提供了三种实用的解决方案。详细阐述了通过JavaScript直接穿透Shadow DOM、利用浏览器工具快速获取JS Path以及使用Python第三方库进行优雅封装的方法,并分享了提升脚本健壮性的实战策略与最佳实践,帮助测试人员有效应对现代Web组件化开发带来的挑战。 阅读详情

相关推荐

【机器人路径规划】基于改进型A*算法的机器人路径规划(Python代码实现)

本文针对传统A算法在机器人路径规划中存在的搜索效率低、路径不平滑等问题,提出了一种改进型A算法。该算法通过引入跳点搜索(JPS)技术优化子节点扩展方式,结合贝塞尔曲线或B样条曲线进行路径平滑处理,并采用动态启发式函数和自适应邻域搜索策略,显著提升了路径规划的效率和路径质量。实验结果表明,改进型A*算法在复杂环境下能有效减少搜索节点数量,缩短路径长度,提高路径平滑性,且具备动态避障能力。

2501_92867626的博客 1582

CurrentHashMap的底层原理

CurrentHashMap在jdk1.8之前使用的是分段锁,在jdk1.8中使用""来保证线程安全。

qq_62923382的博客 3789

独立游戏开发者的新武器:实测腾讯混元3D自动绑骨,搭配Mixamo让角色动画制作效率翻倍

本文实测腾讯混元3D自动绑骨功能与Mixamo动画库的协同使用,显著提升独立游戏开发者的角色动画制作效率。通过解决卡通角色绑骨偏差、优化骨骼权重及动画状态机配置,使原本两周的流程缩短至三天,并分享Unity中的性能优化与版权合规要点。

weixin_42662605的博客 489

currentHashMap说下?怎么做到线程安全的?

7.ConcurrentHashMap在1.8的时候,不在使用分段锁,来保证线程安全。6.ConcurrentHashMap在1.8的底层数据结构使用数组+链表+红黑树。8.而是在初始化Node数组的时候,使用cas+volatile来保证线程安全。2.ConcurrentHashMap在1.7的时候使用分段锁来保证线程安全。5.在扩容的时候,只会对当前访问的段进行扩容,而不是整个map,减少扩容开销。4.每次只锁住当前访问的段,而不是锁定整个map ,可以对不同的段并行更新。

qq_21277357的博客 1005

VS2017配置PCL1.9.1 for win10(超详细)

准备工作 VS2017 自行下载 PCL1.9.1 点击链接跳转Github下载,根据自己的环境选择 win64或win32,作者下载的是:PCL-1.9.1-AllInOne-msvc2017-win64.exepcl-1.9.1-pdb-msvc2017-win64.zip 安装PCL 双击点开PCL-1.9.1-AllInOne-msvc2017-win64.exe,选择Add PCL to the system PATH for all users, 更改安装路径,E:\Progra

malapoa的博客 1144

别再为多相机标定头疼了!用VisionMaster统一坐标系的保姆级教程

本文详细介绍了使用VisionMaster平台解决多相机视觉系统中坐标系统一问题的完整流程。从标定板选择到N点标定,再到实战演练,提供了从原理到落地的全方位指导,帮助工程师高效解决多相机定位引导中的坐标偏差问题。

weixin_38168322的博客 632

currenthashmap线程安全吗

HashMap 是非线程安全的,在多线程环境下使用 HashMap 可能会导致数据不一致的问题。如果需要在多线程环境下使用,可以使用 Collections.synchronizedMap 将 HashMap 转换为线程安全的 Map。也可以使用 ConcurrentHashMap,它是一个线程安全的 Map 实现。 ...

weixin_35756637的博客 473

【数据集】中国大气污染物数据集CHAP(1km空间分辨率)-韦晶团队

中国大气污染物数据集CHAP(1km空间分辨率)-韦晶团队

WW、forever的博客 2595

currenthashmap线程安全的原因

1 线程安全的hash表初始化 由上文可知ConcurrentHashMap是用table这个成员变量来持有hash表的。 table的初始化采用了延迟初始化策略,他会在第一次执行put的时候初始化table。 可通过sizeCtl保证线程安全。 成员变量sizeCtl在ConcurrentHashMap中的其中一个作用相当于HashMap中的threshold,当hash表中元素个数超过sizeCtl时,触发扩容; 他的另一个作用类似于一个标识,例如,当他等于-1的时候,说明已经有某一线程...

g_gstudy的博客 8254

基于Simulink的风电系统背靠背变流器解耦控制仿真

本文完成了基于 Simulink 的风电背靠背变流器解耦控制仿真,实现了:✅掌握 dq 解耦控制的数学本质✅构建 MSC + GSC 完整控制链✅验证其在动态、扰动下的卓越性能✅达成高解耦度、低 THD、稳母线三大目标。

xiaoheshang_123的博客 79

【大模型应用开发-FastAPI框架】(八)Sqlalchemy+postgresql简单增删改查

语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型”。SQLAlchemy的理念是,的量级和性能重要于对象集合;而对象集合的抽象又重要于表和行。因此,SQLAlchemy采用了类似于。社区中成为广泛使用的ORM工具之一,不亚于Django的ORM框架。和declarative等可选插件可以让用户使用声明语法。SQLAlchemy首次发行于2006年2月,并迅速地在。SQLAlchemy“采用简单的。二、安装postgresql。一、SQLAlchemy简介。的数据映射模型,而不是其他。

2098

【线程安全的HashMap有哪些,CurrentHashMap底层是怎么实现线程安全的】

【线程安全的HashMap有哪些,CurrentHashMap底层是怎么实现线程安全的】

学无止境 826

蓝牙功耗优化实战:连接蓝牙耳机时高耗电问题的深度排查与解决

连接任意一款蓝牙耳机, 进行插入实网SIM卡, 同时连接蓝牙耳机后, 进入IDLE模式, 测试时间为10分钟的测试结果, 平均电流毫安在8左右. 测试结果1: 平均电流 8.84mA 测试结果2: 平均电流 7.39mA 厘清问题: 由于出现上两幅图中 绿色线圈中的 20mA 左右高耗电时段, 从而将整体的平均电流抬高. 于是在记录IDLE下电流出现绿色线圈中的 20mA 左右高耗电时段, 同时录制UART1 Catcher log. Filter: MOD_BT/MOD_ATC.

专业开发者的博客,一个从事Android WiFi和蓝牙的工程师 1001

利用Currenthashmap+FutureTask+分布式锁,解决分布式场景下的线程安全问题

举一个例子 某甲方公司要进行招标,来竞标的有A,B,C,D四家公司,每个公司都来了4个人。现有要求在进行产品演示的过程中,每家公司只能出一人与甲方爸爸进行产品演示。 问题 对于甲方爸爸来说,现在要采取一个方案,保证进入会议室的乙方人员只能是一人 正常方案 我们一般情况下的方案是,就设置一个门,乙方公司的人都在门外,每次只允许一个人进去。这样做虽然满足要求,但是效率不高,还容易出错。 优化方案 现在我们设置两道门,第一道门能够保证乙方每个公司都只能进去一个人,那么在第二道门前就只有4个人了,这样效率提高很多,

小唐的博客 906

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

currenthashmap如何实现线程安全_高并发下ConcurrentHashMap到底是怎么实现线程安全的?

前言 这几天一直在看Java并发相关的知识,又学习了很多新的知识。看见大佬们一个个更博速度如此之快,可想知识渊博如滔滔江水。这一周就学习一些并发知识,搭建了一个ftp服务器,不知道小可爱们这周学习了那些知识呢?原文在csdn里,这里复制格式不正确。抛出正题:ConcurrentHashMap是如何实现线程安全,这里面又隐含那些玄机呢?原文:高并发下ConcurrentHashMap到底是怎么实现线...

weixin_39536630的博客 2159

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

currenthashmap如何保证线程安全

将散列分成n段,每一个段都拥有自己的锁,通过继承lock锁来实现的,这样就锁的力度减少了,效率提高了n倍,没个段里面的每个数组有维护了自己的一个hashmap集合,这样来减少我们的冲突。JDK1.8引入了红黑树,将锁的细粒度进一步划分,每一个node的顶级节点,就是hashmap中的数组位置,通过CAS对node的顶级节点。,每一个node下面将力度更一步细分,它还支持协助扩容。在JDK1.7通过分段锁的形式来实现。在JDK1.8通过CAS实现。

weixin_73855020的博客 262

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

currenthashmap如何实现线程安全_Java的List如何实现线程安全?

Java的List如何实现线程安全?Collections.synchronizedList(names);效率最高,线程安全Java的List是我们平时很常用的集合,线程安全对于高并发的场景也十分的重要,那么List如何才能实现线程安全呢 ?加锁首先大家会想到用Vector,这里我们就不讨论了,首先讨论的是加锁,例如下面的代码public class Synchronized{ pri...

weixin_39744894的博客 275

currenthashmap如何解决线程安全

在高并发情况下。HashMap可能出现的致命问题:死循环 HashMap在元素插入过多的时候需要进行Resize,Resize的条件是HashMap.Size>=Capacity*LoadFactor HashMap的Resize包括扩容和ReHash两个步骤,ReHash在并发情况下可能会形成链表环; 并发与并行, 转载于:https://www.cnblogs.com/Aar...

weixin_30621711的博客 703

currenthashmap如何实现线程安全_线程安全的实现方法:POSIX信号量

图控大叔构图传递思想阅读从未如此简单!!!01前言 前些天终于整理完关于IPC机制下的通信方式,现在开始了新的内容板块,虽然还是和线程、进程的通信有关,但是和IPC机制下的内容还是有些差别,废话不多,今天的内容是线程安全的实现方法:POSIX信号量。02干货时间什么是POSIXPOSIX信号量POSIX 信号量分为两种,分别是 POSIX 无名信号量和 POSIX 有名信号量...

weixin_39600400的博客 139

JavaConcurrency-如何理解线程安全的集合CurrentHashMap为例

如果多线程要并发修改一个数据结构 例如: 散列表, 很容易会破坏这个数据结构, 例如: 一个线程可能要开始向表中插入一个新元素,假定在调整散列表各个桶之间的链接关系的过程中,被剥夺了控制权。 如果另一个线程也开始比那里同一个链表,可能使用无效的链接并造成混乱,会爆出异常or陷入死循环。 可以选择锁来保护共享数据结构,但是选择线程安全的实现作为替代可能更容易 高效的映射,集合和队列: java.ut...

其实我也没有太多期盼,毕竟一生太短,少有圆满 606

currenthashmap如何实现线程安全_请问在不加锁的情况下如何保证线程安全?

概念compare and swap,解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要...

weixin_39765796的博客 338

currenthashmap如何实现线程安全_死磕Java并发编程(8):CurrentHashMap如何实现高效地线程安全?

这篇文章一开始我以为会比较简单,但是在深入源码分析时,遇到了很大的阻碍,比前面我们分析AQS以及读写锁的源码要难理解的多,断断续续也写了4天了。 如果你看完还是没有理解的话,那我在这里表示深深的歉意,同时也欢迎你和我一起沟通。本文是死磕Java并发编程系列文章的第 8 篇,主角就是 java 并发包中提供的 CurrentHashMap 这是一个线程安全且高效的HashMap ,也是面试的高频考...

weixin_39611722的博客 3473

currenthashmap如何实现线程安全_Java并发编程实践系列:如何编写线程安全的类

文章目录引言如何设计不变类单例模式的数据库连接管理类ThreadLocal 变量和普通变量的区别引言本章节来聊聊线程安全类的实现方式,日常开发中读者可能都用过的,这里作一个简单的汇总。目前有几种常用的线程安全类的实现方式,悉数如下:设计不变的类,如枚举类;利用同步锁来保证线程操作的安全性,参考示例如何实现线程安全的单例类;使用 ThreadLocal ,每个线程维护自己的复本数据,避免共享数据;如...

weixin_39671509的博客 190

currenthashmap如何实现线程安全_如何保证容器是线程安全的? ConcurrentHashMap 如何高效的线程安全?...

如何保证容器是线程安全的? ConcurrentHashMap 如何高效的线程安全?Java提供了不同层面的线程安全支持。在传统集合框架内部,除了 Hashtable等同步容器,还提供了所谓的同步包装器(Synchronized Wrapper),我们可以调用Collections工具类提供的包装方法,来获取一个同步的包装容器(如 Collections.synchronizedMap),但是它们...

weixin_39690401的博客 368

currenthashmap如何实现线程安全_Java对象的内存分配过程是如何保证线程安全的?...

专注于Java领域优质技术,欢迎关注作者 l Hollis 来源 l Hollis(ID:hollischuang)JVM内存结构,是很重要的知识,相信每一个静心准备过面试的程序员都可以清楚的把堆、栈、方法区等介绍的比较清楚。上图,是一张在作者根据《Java虚拟机规范(Java SE 8)》中描述的JVM运行时内存区域结构画的。很多人都知道Java对象是在堆内存中分配空间的(JIT优化除外),也知...

weixin_39757893的博客 499
上一篇: java多线程易混淆点总结
下一篇: Zookeeper 和 Eureka 之间的区别
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值