Java HashMap和ConcurrentHashMap知识点梳理
jdk 8 HashMap 扩容之后旧元素存放位置是?
java 在扩容的时候会创建一个新的 Node<K,V>[],用于存放扩容之后的值,并将旧的Node数组(其大小记作n)置空;至于旧值移动到新的节点的时候存放于哪个节点是根据 (e.hash & oldCap) == 0 来判断的:
① 等于0时,则将其索引位置h不变;
② 不等于0时,则将该节点在新数组的索引位置等于原索引位置加上旧数组长度。Java 中的另一个线程安全的、与 HashMap 极其类似的类是什么?同样是线程安全,它与 Hashtable 在线程同步上有什么不同?
ConcurrentHashMap 类(是 Java并发包 java.util.concurrent 中提供的一个线程安全且高效的 HashMap 实现)。Hashtable 是使用 synchronized 关键字加锁的原理(就是对对象加锁);而针对 ConcurrentHashMap,在 JDK 7 中采用分段锁的方式,而JDK 8 中直接采用了CAS(无锁算法)+ synchronized。HashMap & ConcurrentHashMap 的区别?
除了加锁,原理上无太大区别。另外,HashMap 的键值对允许有null,但是ConCurrentHashMap 都不允许。为什么 ConcurrentHashMap 比 Hashtable 效率要高?
Hashtable 使用一把锁(锁住整个链表结构)处理并发问题,多个线程竞争一把锁容易导致阻塞;而ConcurrentHashMap降低了锁粒度。ConcurrentHashMap在JDK 7 中使用分段锁(ReentrantLock + Segment + HashEntry),相当于把一个 HashMap 分成多个段,每段分配一把锁,这样支持多线程访问。锁粒度:基于 Segment,包含多个 HashEntry。在JDK 8 中,使用 CAS + synchronized + Node + 红黑树,锁粒度为Node(首结点)(实现 Map.Entry)。ConcurrentHashMap 在 JDK 8 中,为什么要使用内置锁 synchronized 来代替重入锁 ReentrantLock?
①、粒度降低了;
②、JVM 开发团队没有放弃 synchronized,而且基于 JVM 的 synchronized 优化空间更大,更加自然。
③、在大量的数据操作下,对于 JVM 的内存压力,基于 API 的 ReentrantLock 会开销更多的内存。ConcurrentHashMap 的并发度是什么?
程序运行时能够同时更新 ConccurentHashMap 且不产生锁竞争的最大线程数。默认为 16,且可以在构造函数中设置。
当用户设置并发度时,ConcurrentHashMap 会使用大于等于该值的最小2幂指数作为实际并发度(假如用户设置并发度为17,实际并发度则为32)ConcurrentHashMap 加锁机制
它加锁的场景分为两种:
1、没有发生hash冲突的时候,添加元素的位置在数组中是空的,使用CAS的方式来加入元素,这里加锁的粒度是数组中的元素。
2、如果出现了hash冲突,添加的元素的位置在数组中已经有了值,那么又存在三种情况。
(1)key相同,则用新的元素覆盖旧的元素。
(2)如果数组中的元素是链表的形式,那么将新的元素挂载在链表尾部。
(3)如果数组中的元素是红黑树的形式,那么将新的元素加入到红黑树。
第二种场景使用的是synchronized加锁,锁住的对象就是链表头节点(红黑树的根节点)
,加锁的粒度和第一种情况相同。
结论:ConcurrentHashMap分段加锁机制其实锁住的就是数组中的元素,当操作数组中不同的元素时,是不会产生竞争的。ConcurrentHashMap存储对象时(put() 方法):
1> 如果没有初始化,就调用 initTable() 方法来进行初始化;
2> 如果没有哈希冲突就直接 CAS 无锁插入;
3> 如果需要扩容,就先进行扩容;
4> 如果存在哈希冲突,就加锁来保证线程安全,两种情况:一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入;
5> 如果该链表长度大于阀值 8(且数组中元素数量大于64),就要先转换成红黑树的结构。下⾯这个⽅法保证了 HashMap 总是使⽤ 2 的幂作为哈希表的⼤⼩。
/**
* Returns a power of two size for the given target capacity.
*/
static final int tableSizeFor(int cap) {
int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}HashMap红黑树退化为链表的阈值为什么是6?
为了避免频繁地进行链表和红黑树的转化。ConcurrentHashMap get操作需要加锁吗?线程安全吗?
get 方法不需要加锁。因为 Node 的元素 value 和指针 next 是用 volatile 修饰的,在多线程环境下线程A修改节点的 value 或者新增节点的时候是对线程B可见的。这也是它比其它并发集合比如 Hashtable、用 Collections.synchronizedMap()包装的 HashMap 效率高的原因之一。
Java HashMap和ConcurrentHashMap知识点梳理的更多相关文章
- 轻松理解 Java HashMap 和 ConcurrentHashMap
前言 Map 这样的 Key Value 在软件开发中是非常经典的结构,常用于在内存中存放数据. 本篇主要想讨论 ConcurrentHashMap 这样一个并发容器,在正式开始之前我觉得有必要谈谈 ...
- JAVA HashMap与ConcurrentHashMap
HashMap Fast-Fail(遍历时写入操作异常) 在使用迭代器的过程中如果HashMap被修改,那么ConcurrentModificationException将被抛出,也即Fast-fai ...
- HashMap 、ConcurrentHashMap知识点全解析
散列表 在了解hashmap之前,要先知道什么是散列表,因为hashmap就是在散列表结构基础上改造而成的.散列表,也叫哈希表,是根据关键码值(key value)而直接进行访问的数据结构.也就是说, ...
- Java7与Java8中的HashMap和ConcurrentHashMap知识点总结
JAVA7 Java7的ConcurrentHashMap里有多把锁,每一把锁用于其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率呢.这 ...
- [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.
注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...
- Java并发相关知识点梳理和研究
1. 知识点思维导图 (图比较大,可以右键在新窗口打开) 2. 经典的wait()/notify()/notifyAll()实现生产者/消费者编程范式深入分析 & synchronized 注 ...
- java基础知识再学习--HashMap与ConcurrentHashMap的区别
引用:http://blog.csdn.net/xuefeng0707/article/details/40834595 从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是 ...
- Java中关于Map的使用(HashMap、ConcurrentHashMap)
在日常开发中Map可能是Java集合框架中最常用的一个类了,当我们常规使用HashMap时可能会经常看到以下这种代码: Map<Integer, String> hashMap = new ...
- 沉淀再出发:java中的HashMap、ConcurrentHashMap和Hashtable的认识
沉淀再出发:java中的HashMap.ConcurrentHashMap和Hashtable的认识 一.前言 很多知识在学习或者使用了之后总是会忘记的,但是如果把这些只是背后的原理理解了,并且记忆下 ...
- Java并发指南13:Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析
Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析 转自https://www.javadoop.com/post/hashmap#toc7 部分内容转自 http: ...
随机推荐
- C# USB 摄像头 OpenCV 视频picBox呈现,抓拍图像保存呈现。
1.winform 应用程序,两个picturebox空间,一个用于视频呈现,一个用于抓拍呈现. 2.引用包OpenCvSharp4.OpenCvSharp4.Extensions.OpenCvSha ...
- WPF如何使用WebView,并且禁用F12和F5。
客户端套浏览器壳,是如今比较浏览的客户端客户端开发方式.这篇文字简单来介绍一下如何在WPF中使用WebView 安装WebView的nuget包 可以直接执行安装命令 Install-Package ...
- 【Python】批量提取Fibersim xml文件中的节点网格数据
程序功能: 输入需求: fibersim导出的ply 的xml文件,可以很多个也没问题.但名字要有规律,不然没法循环读写.比如我自己用的就是x1.xml.x2.xml.Y1.xml......的文件名 ...
- 记录使用wsl环境nginx代理超时的处理方法
有问题的配置 set $webpack_server http://127.0.0.1:3030; location ~ ^/static-dist { proxy_pass $webpack_ser ...
- 修改npm下载地址为淘宝镜像
修改 npm 下载地址 修改为国内淘宝镜像 # 修改为新淘宝镜像(推荐) npm config set registry https://registry.npmmirror.com/ # 旧 npm ...
- es6 export和export default的区别
相同点 export 与 export default 均可用于导出常量.函数.文件.模块 可在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其 ...
- linux安装python centos
下载安装包 可以到官网 ftp 地址,复制指定 python 版本源码安装包下载链接 https://www.python.org/ftp/python/ 或者到官网 downloads, 复制指定 ...
- windows linux子系统(Ubuntu)ip地址
在Windows10安装好了的子系统(Ubuntu)上,安装了nginx 想去访问,使用ipconfig .ip add,查询来的ip地址都跟自己Windows10的ip完全一样,难道Linux子系统 ...
- V8引擎静态库及其调用方法
V8引擎静态库下载地址由于包含了x86和x64的debug和release静态库,所以资源较大,需要耐心下载. 案例编译工具:VS2019 v8开头的即为V8引擎静态库(附送其它开源静态库libuv. ...
- Docker,vs2019下 使用.net core创建docker镜像 遇到的一些问题
步骤主要分为以下几步: 1.创建docker for linux 的.netcore 项目(vs 自动创建了dockerfile 如果没有需要自己创建在根目录下) 2.编译项目到指定目录下 3.b ...