ConcurrentHashMap扩容】的更多相关文章

前言 这是一篇对 transfer 方法的拾遗,关于之前那篇文章的一些一笔带过,或者当时不知道的地方进行回顾. 疑点 1. 为什么将链表拆成两份的时候,0 在低位,1 在高位? 回顾一下 transfer 的相关代码: int runBit = fh & n; Node<K,V> lastRun = f; for (Node<K,V> p = f.next; p != null; p = p.next) { // 取于桶中每个节点的 hash 值 int b = p.has…
上一个博客中说到了concurrentHashMap的put操作,在put操作之后如果添加了节点,我们首先会把全局的节点数+1,如果满足了扩容条件,我们则进行扩容 我们先从addCount方法说起 /** * 主要有2个功能,计数和扩容想关操作, * x:我们需要增加的值 * check: * 如果check<0 我们不进行扩容工作, * 如果check<1, 我们只在没有发生计数竞争(当前的cell数组没有被创建)的情况下进行扩容工作 * 这边的计数逻辑和LongAddr的计数逻辑相同,主要…
然后,说说精华的部分. Cmap 支持并发扩容,实现方式是,将表拆分,让每个线程处理自己的区间.如下图:     假设总长度是 64 ,每个线程可以分到 16 个桶,各自处理,不会互相影响. 而每个线程在处理自己桶中的数据的时候,是下图这样的:     扩容前的状态. 当对 4 号桶或者 10 号桶进行转移的时候,会将链表拆成两份,规则是根据节点的 hash 值取于 length,如果结果是 0,放在低位,否则放在高位. 因此,10 号桶的数据,黑色节点会放在新表的 10 号位置,白色节点会放在…
前言 理解HashMap和ConcurrentHashMap的重点在于: (1)理解HashMap的数据结构的设计和实现思路 (2)在(1)的基础上,理解ConcurrentHashMap的并发安全的设计和实现思路 前面的文章已经介绍过Map结构的底层实现,这里我们重点放在其扩容方法, 这里分别对JDK7和JDK8版本的HashMap+ConcurrentHashMap来分析: JDK7的HashMap扩容 这个版本的HashMap数据结构还是数组+链表的方式,扩容方法如下: ``` void …
前言 ConcurrentHashMap 是并发中的重中之重,也是最常用的数据结果,之前的文章中,我们介绍了 putVal 方法.并发编程之 ConcurrentHashMap(JDK 1.8) putVal 源码分析.其中分析了 initTable 方法和 putVal 方法,但也留下了一句话: 这篇文章仅仅是 ConcurrentHashMap 的开头,关于 ConcurrentHashMap 里面的精华太多,值得我们好好学习. 说道精华,他的扩容方法绝对是精华,要知道,Concurrent…
ConcurrentHashMap相关的文章网上有很多,而关于ConcurrentHashMap扩容机制是很关键的点,尤其是在并发的情况下实现数组的扩容的问题经常会碰到,看到这篇写的具有代表性,详细讲解了ConcurrentHashMap是如何在并发情况扩容的. 转自简书:占小狼http://www.jianshu.com/u/90ab66c248e6 什么情况会触发扩容 当往hashMap中成功插入一个key/value节点时,有可能触发扩容动作:1.如果新增节点之后,所在链表的元素个数达到了…
HashMap 存储结构 HashMap是数组+链表+红黑树(1.8)实现的. (1)Node[] table,即哈希桶数组.Node是内部类,实现了Map.Entry接口,本质是键值对. static class Node<K,V> implements Map.Entry<K,V> { final int hash; //用来定位数组索引位置 final K key; V value; Node<K,V> next; //链表的下一个node Node(int ha…
Hashtable.ConcurrentHashMap源码分析 为什么把这两个数据结构对比分析呢,相信大家都明白.首先二者都是线程安全的,但是二者保证线程安全的方式却是不同的.废话不多说了,从源码的角度分析一下两者的异同,首先给出二者的继承关系图. Hashtable类属性和方法源码分析 我们还是先给出一张Hashtable类的属性和方法图,其中Entry<K,V>是Hashtable类的静态内部类,该类继承自Map.Entry<K,V>接口.如下将会详细讲解Hashtable类中…
jdk1.7.0_79 HashMap可以说是每个Java程序员用的最多的数据结构之一了,无处不见它的身影.关于HashMap,通常也能说出它不是线程安全的.这篇文章要提到的是在多线程并发环境下的HashMap——ConcurrentHashMap,显然它必然是线程安全的,同样我们不可避免的要讨论散列表,以及它是如何实现线程安全的,它的效率又是怎样的,因为对于映射容器还有一个Hashtable也是线程安全的但它似乎只出现在笔试.面试题里,在现实编码中它已经基本被遗弃. 关于HashMap的线程不…
原文链接:https://www.cnblogs.com/hexinwei1/p/10000779.html 小总结 HashMap.Hashtable.ConcurrentHashMap HashMap:线程不安全 Hashtable:线程安全,每个方法都加了synchronized修饰.类似Collections.synchronizedMap(hashMap) 对读写加锁,独占式,一个线程在读的时候其他线程必须等待,吞吐量较低,性能较为底下 ConcurrentHashMap:利用CAS+…
jdk1.7.0_79 HashMap可以说是每个Java程序员用的最多的数据结构之一了,无处不见它的身影.关于HashMap,通常也能说出它不是线程安全的.这篇文章要提到的是在多线程并发环境下的HashMap——ConcurrentHashMap,显然它必然是线程安全的,同样我们不可避免的要讨论散列表,以及它是如何实现线程安全的,它的效率又是怎样的,因为对于映射容器还有一个Hashtable也是线程安全的但它似乎只出现在笔试.面试题里,在现实编码中它已经基本被遗弃. 关于HashMap的线程不…
前言 每一次总结都意味着重新开始,同时也是为了更好的开始.ConcurrentHashMap 一直是我心中的痛.虽然不敢说完全读懂了,但也看了几个重要的方法,有不少我觉得比较重要的知识点. 然后呢,放一些楼主写的关于 ConcurrentHashMap 相关源码分析的文章链接: ConcurrentHashMap 扩容分析拾遗 并发编程--ConcurrentHashMap#addCount() 分析 并发编程--ConcurrentHashMap#transfer() 扩容逐行分析 并发编程-…
并发编程——ConcurrentHashMap#transfer() 扩容逐行分析 前言 ConcurrentHashMap 是并发中的重中之重,也是最常用的数据结构,之前的文章中,我们介绍了 putVal 方法.并发编程之 ConcurrentHashMap(JDK 1.8) putVal 源码分析.其中分析了 initTable 方法和 putVal 方法,但也留下了一句话: 这篇文章仅仅是 ConcurrentHashMap 的开头,关于 ConcurrentHashMap 里面的精华太多…
参考:https://www.jianshu.com/p/c0642afe03e0 CAS的思想很简单:三个参数,一个当前内存值V.旧的预期值A.即将更新的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false. 细节参考:https://www.jianshu.com/p/fb6e91b013cc 参考:http://blog.csdn.net/u010412719/article/details/52145145 https://www.ji…
在开发中,我们经常使用 HashMap 容器来存储 K-V 键值对,但是在并发多线程的情况下,HashMap 容器又是不安全的,因为在 put 元素的时候,如果触发扩容操作,也就是 rehash ,就会将原数组的内容重新 hash 到新的扩容数组中,但是在扩容这个过程中,其他线程也在进行 put 操作,如果这两个元素 hash 值相同,可能出现同时在同一数组下用链表表示,造成闭环,导致在get时会出现死循环,所以HashMap是线程不安全的. 那有没有安全的 Map 容器呢?有的,目前 JDK…
前言 这是Java并发包最后一个集合框架的数据结构,其复杂程度也较以往任何数据结构复杂的多,顾名思义ConcurrentHashMap是线程安全版本的HashMap,总所周知HashMap是非线程安全的,若直接用于多线程并发环境将会出现很多问题,比如数据丢失,甚至某些操作陷入死循环导致CPU利用率100%等情况.除了ConcurrentHashMap能够保证线程安全之外,还可以通过两种方法获得线程安全的Map结构的实例,要么使用Collections.synchronizedMap(map)返回…
一.简介 上篇文章详细介绍了HashMap的源码及原理,本文趁热打铁继续分析ConcurrentHashMap的原理. 首先在看本文之前,希望对HashMap有一个详细的了解.不然看直接看ConcurrentHashMap的源码还是有些费劲的. 相信对HashMap,HashTable有一定了解,应该知道HashMap是不具备线程安全性的,在resize时会丢数据(JDK8),而HashTable虽然保证了线程安全性,但是其是通过给每个方法加Synchronized关键字达到的同步目的.但是都知…
概述 本文将对JDK8中 ConcurrentHashMap 源码进行一定程度的解读.解读主要分为六个部分:主要属性与相关内部类介绍.构造函数.put过程.扩容过程.size过程.get过程.与JDK7实现的简单对比.希望对读者学习ConcurrentHashMap有一定的帮助. 阅读本文前,可能需要读者对HashMap和红黑树等有基本的了解. 主要属性和主要的内部类 主要属性 常量 ConcurrentHashMap中常量一共分为以下几个部分: 容量相关:MAXIMUM_CAPACITY.DE…
如果有一个整型变量count,多个线程并发让count自增1,你会怎么设计? 你知道如何让多个线程协作完成一件事件吗? 前言 很高兴遇见你~ ConcurrentHashMap是个老生常谈的集合类了,我们都知道多线程环境下不能直接使用HashMap,而需要使用ConcurrentHashMap,但有没有了解过ConcurrentHashMap到底是如何实现线程安全的呢?他到底跟传统的Hashtable和SynchronizeMap(没听过SynchronizeMap?他就是Collections…
目录 前言 ConcurrentHashMap 原理 JDK1.8 版本 ConcurrentHashMap 做了什么改进 为什么 key 和 value 不允许为 null ConcurrentHashMap 如何保证线程的安全性 如何用 CAS 保证数组初始化的安全 put 操作如何保证数组元素的可见性 精妙的计数方式 addCount 计数方法 fullAddCount 方法 初始化 CounterCell 数组 CounterCell 如何赋值 技数数组 CounterCell 也能扩容…
C# 求精简用一行代码完成的多项判断 重复赋值 哈哈,说实话,个人看着这么长的三元操作也麻烦,但是我也只想到了这样三元判断句中执行方法体能够写到一行,追求的终极目的是,用一行实现这个过程,而且简单,由于篇幅,我就不截图我其实是放在一行上的 讨论的重点是怎么做的更极致,而不是这样搞规范不规范,求更有创意的写法... .. ..华丽丽的分割线.. .. var turecolor = colorJToken.OfType<JProperty>().Sum(d => (int)d.Value…
前言 只有光头才能变强 本文力求简单讲清每个知识点,希望大家看完能有所收获 一.如何减少线程上下文切换 使用多线程时,不是多线程能提升程序的执行速度,使用多线程是为了更好地利用CPU资源! 程序在执行时,多线程是CPU通过给每个线程分配CPU时间片来实现的,时间片是CPU分配给每个线程执行的时间,因时间片非常短,所以CPU通过不停地切换线程执行. 线程不是越多就越好的,因为线程上下文切换是有性能损耗的,在使用多线程的同时需要考虑如何减少上下文切换 一般来说有以下几条经验 无锁并发编程.多线程竞争…
1. ConcurrentHashMap 2. ConcurrentLinkedQueue 3. ConcurrentSkipListMap 4. ConcurrentSkipListSet 5. txt java 并发容器 ConcurrentHashMap 并发编程中需要用到线程安全的HashMap 为什么要用 1. 线程不安全的HashMap 数据丢失:put的时候导致的多线程数据不一致 比如有两个线程A和B,首先A希望插入一个key-value对到HashMap中,首先计算记录所要落到的…
AndroidS Studio打包APK时出现问题:org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:lintVitalRelease'. 什么意思?任务':app:lintVitalRelease的执行失败. 关于lint是个什么东西看官网:https://developer.android.com/studio/write/lint?hl=zh-CN 或者:https://blog.csd…
本篇文章站在多线程并发安全角度,带你了解多线程并发使用 HashMap 将会引发的问题,深入学习 ConcurrentHashMap ,带你彻底掌握这些核心技术. 全文摘要: HashMap 核心技术 ConcurrentHashMap 核心技术 分段锁实战应用 HashMap HashMap 是我们经常会用到的集合类,JDK 1.7 之前底层使用了数组加链表的组合结构,如下图所示: 新添加的元素通过取模的方式,定位 Table 数组位置,然后将元素加入链表头部,这样下次提取时就可以快速被访问到…
本文主要是自己阅读了HashMap和ConcurrentHashMap源码及一些Java容器类相关的博客后,找了一些很多面经中涉及到的Java容器相关的面试题,自己全部手写的解答,也花了一些流程图,之后会继续更新这一部分. HashMap相关的面试题 1.HashMap添加一个键值对的过程是怎么样的? 2.ConcurrentHashMap添加一个键值对的过程是怎么样的? 3.HashMap与HashTable,ConcurrentHashMap的区别是什么? 4.HashMap扩容后是否需要r…
点赞再看,养成习惯,微信搜索[三太子敖丙]关注这个互联网苟且偷生的工具人. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文章. 前言 前段时间敖丙不是在复习嘛,很多小伙伴也想要我的复习路线,以及我自己笔记里面的一些知识点,好了,丙丙花了一个月的时间,整整一个月啊,给大家整理出来了. 一上来我就放个大招好吧,我的复习脑图,可以说是全得不行,为了防止被盗图,我加了水印哈. 这期看下去你会发现很硬核,而且我会持续更新,…
源代码查看,有三个常量, static final int DEFAULT_INITIAL_CAPACITY = 16; static final int MAXIMUM_CAPACITY = 1 << 30; static final float DEFAULT_LOAD_FACTOR = 0.75f; 三个常量中可以看出,默认的容器大小是16,最大长度是2的30次方,load factor默认是0.75,扩充的临界值是16*0.75=12 当我们往HashMap中put元素的时候,先根据k…
题外话:为什么要hashcode进行spread? 充分使用key.hashCode()的高16位信息,保证hash分布更分散, 扩容操作是新建2倍于原表大小的新表,并将原表结点拷贝一份放在新表中,对原表无修改或修改很小.当原表所有结点都已被拷贝到新表中后,原表会被垃圾回收. 在jdk7中的HashMap实现类中,数组+链表.扩容操作是将原数组的结点一一进行hash计算,然后一一挂接到新数组上,所以不是基于复制结点的机制.在jdk7中的ConcurrentHashMap实现类中,段(segmen…
本文介绍Redis的字典(是种Map)扩容与ConcurrentHashMap的扩容策略,并比较它们的优缺点. (不讨论它们的实现细节) 首先Redis的字典采用的是一种‘’单线程渐进式rehash‘’,这里的单线程是指只有一个线程在扩容, 而在扩容的同时其他的线程可以并发的进行读写. Redis系统后台会定时给予扩容的那个线程足够的运行时间,这样不会导致它饿死. 大致过程是这样的: ht[0],是存放数据的table,作为非扩容时容器. ht[1],只有正在进行扩容时才会使用,它也是存放数据的…