Java基础(7)-ConcurrentHashMap与CAS

JDK1.7中ConcurrentHashMap全源码解读(CAS锁、分段锁) Segment分段锁机制,CAS锁机制,ConcurrentHashMapJDK1.7源码分析,ConcurrentHashMap的put方法、remove方法、get方法源码分析,ConcurrentHashMap锁的机制。RentrantLock,自旋锁,ConcurrentHashMap扩容机制,在1.7下存在的问题 阅读详情

ConcurrentHashMap是J.U.C包下一个十分重要的并发容器之一,它和Hashtable一样是并发安全的,但是它的性能却比Hashtable好很多,且由于在高并发环境下,使用HashMap的put方法时会造成堵塞,这将会消耗许多的CPU时间片,造成不必要的等待,所以在并发情况下应当使用ConcurrentHashMap替代HashMap

1.1 JDK 5中ConcurrentHashMap的实现原理

早期的ConcurrenntHashMap通过分段锁Segment和HashEntry细化了锁的范围,实现了并发安全,由于不像Hashtable一样使用全局锁, 而是细分锁的数据规模,所以性能上比同步的Hashtable高了许多,详细了解可以阅读这篇文章:
https://www.cnblogs.com/ITtangtang/p/3948786.html

在这里插入图片描述

1.2 JDK 8中ConcurrentHashMap的实现原理

原理:使用CAS技术与同步锁技术相结合

1.不允许插入null键或null值
2.putAll源码中,不直接使用Java层次级别的数组更新,而是使用CAS的方式直接从系统底层内存空间中更新,所以并发安全

	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) {
            //通过cas进行添加
                if (casTabAt(tab, i, null,
                             new Node<K,V>(hash, key, value, null)))
                    break;                    
            }
            //....

1.3 CAS基本原理

CAS 全称是 compare and swap,即比较和交换,是一种用于在多线程环境下实现同步功能的机制。CAS 操作包含三个操作数: 内存位置、预期数值和新值。CAS 的实现逻辑是将内存位置处的数值与预期数值相比较,若相等,则说明没有其他线程对其进行过修改,将内存位置处的值替换为新值。若不相等,则说明有其他线程对其进行了修改,不做任何操作,即原地自旋等待

在 Java 中,Java 并没有直接实现 CAS,CAS 相关的实现是通过 C++ 内联汇编的形式实现的。Java 代码需通过 JNI 才能调用。

像synchronized这种独占锁属于悲观锁,它是在假设一定会发生冲突的,那么加锁恰好有用,除此之外,还有乐观锁,乐观锁的含义就是假设没有发生冲突,那么我正好可以进行某项操作,如果要是发生冲突呢,那就重试直到成功,乐观锁最常见的就是CAS。

1.4 ABA问题

CAS 由三个步骤组成,分别是“读取->比较->写回”。考虑这样一种情况,线程1和线程2同时执行 CAS 逻辑,两个线程的执行顺序如下:

时刻1:线程1执行读取操作,获取原值 A,然后线程被切换走
时刻2:线程2执行完成 CAS 操作将原值由 A 修改为 B
时刻3:线程2再次执行 CAS 操作,并将原值由 B 修改为 A
时刻4:线程1恢复运行,将比较值与原值进行比较,发现两个值相等。然后用新值写入内存中,完成 CAS 操作
如上流程,线程1并不知道原值已经被修改过了,在它看来并没什么变化,所以它会继续往下执行流程。

对于 ABA 问题,通常的处理措施是对每一次 CAS 操作设置版本号。J.U.C包下提供了一个可处理 ABA 问题的原子类 AtomicStampedReferenc,具体可以查阅资料了解

ConcurrentHashMap和CAS就先简单地了解到这里吧…查阅其他资料看到的都是cpp和汇编的解读,看得一头雾水,我太难了,就先这样吧(゜-゜)つロ (干杯)

java并发实践--ConcurrentHashMap与CAS 最近在做接口限流时涉及到了一个有意思问题,牵扯出了关于concurrentHashMap的一些用法,以及CAS的一些概念。限流算法很多,我主要就以最简单的计数器法来做引。先抽象化一下需求:统计每个接口访问的次数。一个接口对应一个url,也就是一个字符串,每调用一次对其进行加一处理。可能出现的问题主要有三个: 多线程访问,需要选择合适的并发容器 分布式下多个实例统计接口流量需要共享内存 流量统计应该尽 阅读详情

相关推荐

ConcurrentHashMap 1.8

它的冲突再达到一定大小时会转化成红黑树,在冲突小于一定数量时又退回链表。即为当前 key 定位出的 Node,如果为空表示当前位置可以写入数据,利用 CAS 尝试写入,失败则自旋保证成功。可以发现 Java8 的 ConcurrentHashMap 相对于 Java7 来说变化比较大,不再是之前的。使用的分段锁,也就是每一个 Segment 上同时只有一个线程可以操作,每一个。(sizeControl 的缩写),它的值决定着当前的初始化状态。数组的结构,它可以扩容,它的冲突会转化为链表。

些许风霜罢了 1221

ConcurrentHashMap中CAS是什么

JVM内存模型是Java虚拟机规范中定义的一套内存访问规则,用于规定多线程访问共享内存时的行为和保证线程安全。JVM内存模型规定了Java程序在执行时,内存是如何被划分和访问的。JVM内存模型将内存分为两种类型:线程私有内存和线程共享内存。线程私有内存包括程序计数器、Java虚拟机栈和本地方法栈,每个线程都有自己的一份,用于存储线程私有的数据。线程共享内存包括Java堆、方法区和运行时常量池,所有线程都共享这部分内存。JVM内存模型规定了多线程访问共享内存时的原子性、可见性和有序性。

我的博客 3055

翻了ConcurrentHashMap1.7 和1.8的源码,我总结了它们的主要区别。

Java7 中 ConcurrentHashMap 使用的分段锁,也就是每一个 Segment 上同时只有一个线程可以操作,每一个 Segment 都是一个类似 HashMap 数组的结构,它可以扩容,它的冲突会转化为链表。但是 Segment 的个数一但初始化就不能改变。Java8 中的 ConcurrentHashMap 使用的 Synchronized 锁加 CAS 的机制。结构也由 Java7 中的Segment 数组 + HashEntry 数组 + 链表进化成了。

m0_73311735的博客 966

从concurrentHashMap看CAS的基础原理

今天在看concurrentHashMap的时候,知道在jdk1.8之后,这个集合的并发控制使用Synchronized和CAS来操作,所以就想找博客看看CAS。 看到这篇文章,感觉还不错,加上自己的些许理解,转载在这里。 https://blog.youkuaiyun.com/mmoren/article/details/79185862 本篇的思路是先阐明无锁执行者CAS的核心算法原理然后分析Jav...

默默的笔记 1万+

什么是ConcurrentHashMap?

然后在 Segment 里进行插入操作,插入操作需要经历两个步骤,第一步判断是否需要对 Segment 里的 HashEntry 数组进行扩容,第二步定位添加元素的位置,然后将其放在 HashEntry 数组里。这里面的第一步中的 scanAndLockForPut 操作这里没有介绍,这个方法做的操作就是不断的自旋 tryLock() 获取锁。更新一个数据的时候,会去判断当前内存地址中的当前值是否跟预期值是否相等,如果相等,则用新值更新内存地址中的值。如果不是,则不更新值,并返回当前的实际值。

m0_64210833的博客 1929

STM32单片机语音提示盲人拐杖整点报时夜间警示超声波测距

STM32单片机语音提示盲人拐杖整点报时夜间警示超声波测距 关键词:语音提示盲人拐杖 整点报时 超声波测距拐杖

LS840233684的博客 2048

Java ConcurrentHashMap 1.7 vs 1.8:从分段锁到CAS+Synchronized的进化之路!

对比维度JDK 1.7JDK 1.8数据结构Segment数组 + HashEntry数组 + 链表Node数组 + 链表 + 红黑树锁机制ReentrantLock(分段锁)CAS + synchronized(桶锁)锁粒度Segment级别(默认16)单个桶级别(动态)查询复杂度O(n)(链表遍历)O(1)链表 / O(log n)红黑树扩容方式单线程、Segment独立扩容多线程协同、全表扩容链表插入头插法(有死循环风险)尾插法(安全)size()实现遍历加锁统计。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 416

Pico设备手势追踪实战:5步搞定MRTK3手部模型与UI交互配置

本文详细介绍了在Pico设备上使用MRTK3实现手势追踪的5个关键步骤,包括环境配置、手部模型冲突解决、射线交互优化、UI交互配置及性能优化。通过实战案例和代码示例,帮助开发者快速解决MR开发中的常见问题,提升混合现实应用的交互体验。

onion的博客 500

java并发编程ConcurrentHashMap(1.7分段锁和1.8CAS+同步锁)扩容机制补充

东西很多,我就按照其他博客进行分类整理 1.7锁分段技术 https://blog.youkuaiyun.com/yansong_8686/article/details/50664351 结构如下,锁分段成数组,每个分段下面存kv Segment是可重入锁 哈希分散后能够更均匀的分配到各个Segment上 get不加锁,很快,关键在于volatile保证可见性,但不保证原子性 put对分段Segment加锁,Segment提高效率的地方就在于操作时不需要对整个hashMap都加锁。之后和普通map一样都要考虑

Koikoi12的博客 2400

libiec61850实战:手把手教你用C语言动态获取IED设备模型(附完整代码解析)

本文详细介绍了如何使用libiec61850库通过C语言动态获取IED设备模型,包括环境配置、连接建立、模型遍历及错误处理等关键步骤。通过完整的代码示例和实战案例,帮助开发者掌握智能变电站通信中的核心技术,提升工业自动化系统的开发效率。

weixin_42519985的博客 435

Calibre LVS错误排查实战:从Innovus到GDS的完整调试流程(附常见错误解析)

本文详细介绍了数字IC后端设计中,从Innovus工具输出数据到Calibre LVS物理验证的完整调试流程。文章系统性地讲解了LVS错误排查的方法论,包括报告解读、图形化定位以及针对器件不匹配、电源网络错误、短路开路等常见问题的深度解析与解决方案,旨在帮助工程师高效完成版图与原理图的一致性检查。

weixin_29218963的博客 778

Java ConcurrentHashMap - 详解

本文介绍了Java中的ConcurrentHashMap(CHM),重点分析了其线程安全机制和性能优化。CHM通过分段锁(Java7)和CAS+synchronized(Java8)技术实现高并发访问,相比Hashtable显著提升了性能。Java8版本将锁粒度细化到单个桶,支持函数式API,并优化了数据结构(数组+链表/红黑树)。文章还详细说明了CHM的关键特性(弱一致性迭代器、禁止null值等)、常用原子操作方法(putIfAbsent、compute等)以及适用场景(高并发缓存)。正确使用CHM需要注

M_Reus_11的博客 908

每天一个优秀提示词学习收藏 - 文本去AI化(四)

宝子们,今天不藏私啦!我把这段时间四处搜罗、潜心钻研出来的文本去AI化Prompt 提示词大礼包双手奉上,这可都是能让你的 AI 创作水平原地起飞的干货!走过路过不要错过,赶紧码住,开启你的 AI 创作进阶之旅吧!

2451

一文弄懂Java中ConcurrentHashMap的底层原理

在 JDK1.7 的时候,ConcurrentHashMap 对整个桶数组进行了分割分段(Segment,分段锁),每一把锁只锁容器其中一部分数据(下面有示意图),多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率

LUCIAZZZ的博客 1457

从零上手:基于英飞凌TC377的UDE STK 5.0实战调试指南

本文详细介绍了基于英飞凌TC377芯片和UDE STK 5.0的实战调试指南,涵盖硬件连接、工作空间配置、程序烧录、多核调试等关键步骤。特别针对汽车电子领域常见的多核架构调试难题,提供了断点设置、变量监控等实用技巧,帮助开发者快速上手并优化调试效率。

weixin_30839881的博客 685

Frida精准定位Shopee x-sap-ri动态签名生成函数

x-sap-ri是Shopee客户端生成的上下文感知型动态令牌,本质为基于设备标识、请求路径与毫秒级时间戳三元组的SHA256哈希值,经Base64编码后作为防重放与防批量伪造的核心校验字段。其生成逻辑深度混淆且跨Java/Native层,静态分析失效,而Frida凭借内存级函数调用拦截与JNI层穿透能力,成为唯一可行的技术路径。本文聚焦Frida在加固App中的实战适配——通过libcrypto.so API特征扫描反向定位被抹名的生成函数,实现对x-sap-ri输入参数(如16字节device_id加密

weixin_33978578的博客 612

Java7与Java8中的ConcurrentHashMap

JAVA7 Java7的ConcurrentHashMap里有多把锁,每一把锁用于其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率呢。这就是“锁分离”技术。 ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁(继承了ReentrantLock),在Con...

weixin_30516243的博客 140

2025_NIPS_Grounded Reinforcement Learning for Visual Reasoning

尽管基于思维链的强化学习已在数学、编程等任务中显著提升语言模型性能,但视觉推理面临额外复杂性——需模型引导视觉注意力、解读感知输入,并将抽象推理锚定到空间证据上。本文提出ViGoRL(视觉接地强化学习),这是一种通过强化学习训练的视觉语言模型,能将每个推理步骤明确锚定到特定视觉坐标。受人类视觉决策启发,ViGoRL学会生成空间接地的推理轨迹,在每个步骤引导视觉注意力聚焦任务相关区域。当需要细粒度探索时,我们提出的多轮强化学习框架允许模型随着推理展开动态缩放至预测坐标。

c_cpp_csharp的专栏 59

深入理解 Java 中的 ConcurrentHashMap:为什么它是线程安全的?

本文解析了Java中ConcurrentHashMap的线程安全机制。首先指出了HashMap在多线程环境下存在的问题:数据覆盖、环形链表和缺乏同步措施。接着详细对比了JDK 7和JDK 8的实现方式:JDK 7采用分段锁(Segment)机制,每个Segment独立加锁;JDK 8则改用更精细的CAS+synchronized+红黑树方案,通过桶级别锁和volatile保证可见性。文章通过代码示例展示了线程安全的具体实现,包括get操作的无锁读取、put操作的CAS自旋和桶锁机制,以及扩容时的并发控制策略

qq_46371374的博客 1225

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

ConcurrentHashMap源码分析

基本原理 Java7 基本数据模型:数组+Segment<K,V>[] segments+HashEntry<K,V>[] table+链表组成,锁通过Cas+Lock锁实现。 基本原理简介:ConcurrentHashMap由一个个 Segment 组成,Segment 代表部分或分段的意思,所以很多地方都会将其描述为分段锁。 通俗易懂的说,ConcurrentHashMap 是一个Segment数组,Segment通过继承 ReentrantLo...

I Belivs I Can! 439

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【Java开发日记】我们来说一说 ConcurrentHashMap 中十个提升性能的细节

在看完的哪些操作需要加锁?答:只有写入操作才需要加锁,读取操作不需要加锁的无锁读是如何实现的?答:首先HashEntry中的value和next都是有volatile修饰的,其次在写入操作的时候通过调用UNSAFE库延迟同步了主存,保证了数据的一致性在多线程的场景下调用size()方法获取的大小有什么挑战?是怎么解决的?size()具有全局的语义,如何能保证在不加全局锁的情况下读取到全局状态的值是一个很大的挑战,通过查看两次无锁读中间是否发生了写入操作来决定读取到的size()

纵有疾风起 人生不言弃 1352

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

ConcurrentHashMap–面试必备的源码分析

Java7 中使用的分段锁,也就是每一个 Segment 上同时只有一个线程可以操作,每一个Segment都是一个类似HashMap数组的结构,它可以扩容,它的冲突会转化为链表。但是Segment的个数一但初始化就不能改变。Java8 中的使用的锁加 CAS 的机制。结构也由 Java7 中的 Segment数组 +HashEntry数组 + 链表进化成了Node 数组 + 链表 / 红黑树,Node 是类似于一个 HashEntry 的结构。

qq_51321722的博客 757

关于ConcurrentHashMap的深刻理解

是 Java 中一个线程安全且高效的哈希表实现,它位于包下,在多线程环境下可以替代HashTable和同步包装器。以下将详细介绍的底层原理和常用使用方法。

qq_29360589的博客 1312

【Java 基础】ConcurrentHashMap 底层原理

ConcurrentHashMap 是线程安全的哈希表,它是 Java 并发包中提供的一种高效的并发 Map 实现。ConcurrentHashMap 底层采用了分段锁的机制,不同的段(Segment)可以被不同的线程同时访问,从而提高了并发性能。

激流丶的博客 5643

Java常见技术分享-18-多线程安全-进阶模块-并发集合与线程池-ConcurrentHashMap

当线程尝试 去 设置 值的时候,比如put(key , value ) ,根据 key找到对应的下标, 然后在插入的操作前 去内存读取 数组中这个下标 对应的 链表头节点(【该数组索引位的旧头节点的引用】), 接着就会执行CAS操作 , compare比较的是 自己当前感知到的 【该数组索引位的旧头节点的引用】, 把这个当作预期值, 如果预期值一致, 那么把 这个索引位 的值更新成 新节点的引用, 这个新节点 后面理论上就是旧的节点。核心实现: CAS加上synchronized。

2501_94453464的博客 179

Java并发集合进化史:ConcurrentHashMap 1.7和1.8全面对比——从分段锁到CAS+synchronized

ConcurrentHashMap是Java并发编程中最常用的线程安全哈希表。从JDK 1.7到JDK 1.8,其底层实现发生了革命性的变化:从分段锁机制演进为,大幅提升了并发性能和扩展性。本文将全面对比两个版本的差异,深入剖析各自的实现原理。fill:#333;important;important;fill:none;CHM总结JDK 1.7特点分段锁16个SegmentHashEntry链表头插法独立扩容JDK 1.8改进桶级别锁红黑树优化尾插法多线程扩容使用建议。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 984
上一篇: Java基础(6)-ArrayList和LinkedList一览
下一篇: 计网学习笔记(3)-Http协议总结
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值