网站首页 > 文章精选 正文
概念
在多线程高并发环境下,使用HashMap进行put、remove操作时存在数据丢失的情况,也就是说HashMap是非线程安全的,因为HashMap底层代码操作数组的数据并未加锁,为了避免这个隐患,强烈推荐使用ConcurrentHashMap代替HashMap。
HashTable是一个线程安全类,实际上它底层使用 synchronized 来锁住整张 hash 表来实现线程安全,即每次锁住整张表让线程独占,相当一所有的线程进行读写时都去竞争同一把锁,导致效率非常低下,而ConcurrentHashMap可以做到读取数据的时候不加锁,并且其内部结果可以让其在进行写操作的时候能把锁的颗粒度保持尽量最小,允许多个修改操作同时进行,其关键于使用了分段锁机制,它使用了多个锁来控制对hash表的不同部分就那些修改。
对于JDK1.7版本的实现,ConcurrentHashMap内部使用段(Segemnt)来说表示不同的16个部分,也就是一个 Segment 数组,一个 Segment 数组里面包含 HashEntry 数组,当对某个 HashEntry 数组中的元素进行修改时,必须首先获得该元素所属 HashEntry 数组对应的 Segment 锁,每个Segment都有自己独立的锁,只要多个修改操作发生在不同段上,它们就可以并行执行。
JDK1.8的实现降低了锁的颗粒度,不同于JDK1.7版本的Segemnt数组+HashEntry链表,JDK1.8版本中的ConcurrentHashMap直接抛弃了Segment锁,一个ConcurrentHashMap包含一个Node数组(和HashEntry实现差不多),每个Node是一个链表结构,并且在链表长度大于一定值时会自动转换为红黑树结构(TreeBin)。
对比
- HashMap
- 数据结构:数组+链表
- 安全性:非线程安全,操作数组的数据并未加锁。
- HashTable
- 数据结构:数组+链表
- 线程安全:线程安全,数组是HashMap为主体,链表则主要是解决哈希冲突而存在的。
- ConcurrentHashMap
- JDK1.7
- 数据结构:Segment 分段数组 + HashEntry 数组
- 线程安全:线程安全,因为底层代码在操作每一个Segment时都会加锁,保证线程安全
- 性能:读取数据不加锁、效,且因为map中的value变量值是添加volatile关键字修饰,可保证读取到最新值,降低CPU负载。
- JDK1.8
- 数据结构:Node数组 + 链表 + 红黑树(TreeBin)
- 线程安全:线程安全,并发操作使用的是synchronized和CAS来控制,引入了红黑树结构降低哈希冲突和时间复杂度。
HashMap和ConcurrentHashMap示意图:
ConcurrentHashMap在JDK 7和8之间的区别
- JDK1.8的实现降低锁的粒度,JDK1.7版本锁的粒度是基于Segment的,包含多个HashEntry,而JDK1.8锁的粒度就是HashEntry(首节点)。
- JDK1.8版本的数据结构变得更加简单,使得操作也更加清晰流畅,因为已经使用synchronized来进行同步,所以不需要分段锁的概念,也就不需要Segment这种数据结构了,由于粒度的降低,实现的复杂度也增加了。
- JDK1.8使用红黑树来优化链表,基于长度很长的链表的遍历是一个很漫长的过程,而红黑树的遍历效率是很快的,代替一定阈值的链表,这样形成一个最佳拍档。
作者:austin流川枫
链接:
https://juejin.cn/post/7115635447790829598
猜你喜欢
- 2025-03-18 系统性能优化与Java代码编写性能考虑
- 2025-03-18 面试必问之:Java 中 == 和 equals 的区别你知道吗
- 2025-03-18 为什么重写 equals时必须重写 hashCode 方法?
- 2025-03-18 一网打尽-HashMap面试题(面试hashmap底层实现原理)
- 2025-03-18 HashMap面试知识点合集,这一篇就够了
- 2025-03-18 Java并发系列 | ConcurrentHashMap源码分析
- 2025-03-18 ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)
- 2025-03-18 HashMap底层实现原理以及线程安全实现
- 2025-03-18 不怕面试再问HashMap,一次彻底地梳理(原理+手写实现)
- 2025-03-18 java面试题——HashMap相关面试题
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 稳压管的稳压区是工作在什么区 (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)