ConcurrentHashMap源码
----------------------------------------------------------------------------------------------------------
TheadLocalRandom初始化是把当前线程自己的的种子threadLocalRandomSeed和随机数threadLocalRandomProbe两个属性设置了,getProbe方法其实是用unsafe取当前线程对象中取出随机数的值
-------------------------------------------------------------------------------------------------------
进入fullAddCount方法就意味着并发量很高,cas修改baseCount出现失败的情况了,需要往辅助的储存格里暂存。其实CounterCells就是一个根据并发压力不断2-4-8-16这样扩容的一个数组。不同线程根据随机数hash之后有可能使用同一个格子,所以要有一个全局锁cellsbusy,避免初始化格子数组或者当前格子的时候,并发冲突。ThreadLocalRandom.advanceProbe,同一个格子位并发太高还可以重新生成随机数。
---------------------------------------------------------------------------------------------------------
helpTransfer的核心方法是transfer,在调用之前先做判断(别处调用transfer之前都一样):
一:如果sizeCtl为负,说明此时已经有线程已经开始transfer,那么把当前的sizeCtl+1,这个和ReentrantLock的共享锁是一样的。
二,如果不为负,说明当前线程是第一个开始扩容的,会resizeStamp一下,得到一个保存有tablelength信息的负数(为什么要+2)再替换sizeCtl。
关于sizeCtl:
在transfer中,while(advance)中会判断,如果交替扩容使得transferIndex<=0,说明所有的按stride长度分割的所有区域都已经有线程或正在扩容或已扩容完毕
那么先把自己当前线程的i设置为-1,就可以进入将sizeCtl减一的操作,使得当前线程结束扩容,当前线程退出扩容前,要先通过 sizeCtl减完自己的1之后是否是之前说的resizeStamp右移再加2,.
如果是,说明其他线程都扩容完毕,自己是最后一个线程,那么把newTable属性设置为null,当前table指向newTable,sizeCtl变为新table长度的0.75倍。如果不是,说明还有别的线程在扩容,那么直接返回。
--------------------------------------------------------------------------------------------------------------
stride是并发扩容分区的跨度,table长度不是太大的话一直是16,很大的话会相应扩大。第一个线程A从table最底端开始扩容,下一个线程B(B有可能是A)跨度到tableLength-stride*1的位置开始扩容,下一个线程C跨度到tableLength-stride*2的位置开始扩容。
判断扩容线程数的逻辑在上面,判断从哪个位置开始扩容是在while(advance)中,借助transferIndex 这个变量。分段扩容可以避免并发冲突(冲突发生在比如每次tabAt==null之后的cas为fwdNode,和tabAt!=null的synchronized)
扩容的时候,旧table的链表(或者红黑树)在新table中,被重新hash之后分成两个链表,如果其中有链表长度大于转成红黑树阈值,那么在赋值给新table对应槽位的时候,在红黑树化。换句话说,也就是旧table有旧的链表指向所有的k,v。新链表也有新的两条链表分
别指向原来的k,v。这就是为什么扩容的同时查找并不会受链表一分为二影响。
------------------------------------------------------------------------------------------------------------------
put remove 略
ConcurrentHashMap源码的更多相关文章
- JDK1.7 ConcurrentHashMap 源码浅析
概述 ConcurrentHashMap是HashMap的线程安全版本,使用了分段加锁的方案,在高并发时有比较好的性能. 本文分析JDK1.7中ConcurrentHashMap的实现. 正文 Con ...
- Hashtable、ConcurrentHashMap源码分析
Hashtable.ConcurrentHashMap源码分析 为什么把这两个数据结构对比分析呢,相信大家都明白.首先二者都是线程安全的,但是二者保证线程安全的方式却是不同的.废话不多说了,从源码的角 ...
- ConcurrentHashMap源码分析(一)
本篇博客的目录: 前言 一:ConcurrentHashMap简介 二:ConcurrentHashMap的内部实现 三:总结 前言:HashMap很多人都熟悉吧,它是我们平时编程中高频率出现的一种集 ...
- ConcurrentHashMap 源码分析
ConcurrentHashMap 源码分析 1. 前言 终于到这个类了,其实在前面很过很多次这个类,因为这个类代码量比较大,并且涉及到并发的问题,还有一点就是这个代码有些真的晦涩,不好懂.前前 ...
- 死磕 java集合之ConcurrentHashMap源码分析(三)
本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样 ...
- JDK12 concurrenthashmap源码阅读
本文部分照片和代码分析来自文末参考资料 java8中的concurrenthashmap的方法逻辑和注解有些问题,建议看最新的JDK版本 建议阅读 concu ...
- 并发-ConcurrentHashMap源码分析
ConcurrentHashMap 参考: http://www.cnblogs.com/chengxiao/p/6842045.html https://my.oschina.net/hosee/b ...
- 数据结构算法 - ConcurrentHashMap 源码解析
五个线程同时往 HashMap 中 put 数据会发生什么? ConcurrentHashMap 是怎么保证线程安全的? 在分析 HashMap 源码时还遗留这两个问题,这次我们站在 Java 多线程 ...
- ConcurrentHashMap源码走读
目录 ConcurrentHashMap源码走读 简介 放入数据 容器元素总数更新 容器扩容 协助扩容 遍历 ConcurrentHashMap源码走读 简介 在从JDK8开始,为了提高并发度,Con ...
- JDK8中的ConcurrentHashMap源码
背景 上文JDK8中的HashMap源码写了HashMap,这次写ConcurrentHashMap ConcurrentHashMap源码 /** * Maps the specified key ...
随机推荐
- day22
# day22 ## 复习 ```python# 1.内存管理# 引用计数:垃圾回收机制工作原理# -- 引用就 +1 ,释放就 -1 , 当计数为0时,就会被垃圾回收机制回收 # 标记清除:解决循环 ...
- 如何为Rails作贡献:例增加rich_text field generators
如何为Rails作贡献 例增加rich_text field generators 下载https://github.com/rails/rails 打开atom,在 rails/railties/l ...
- 从身份证管理系统思考企业CMDB的建设
关注嘉为科技,获取运维新知 对大部分中大型的企业来说,CMDB建设对于整个IT服务和IT运维管理的重要性不言而喻,但是目前仍然有非常多的企业无法建设好CMDB. 我最近刚好接触了一个公安系统的朋友,他 ...
- sql group by聚合函数
如何让分组后count计算结果为0的记录也显示
- 8.6 GOF设计模式四: 策略模式… Strategy Pattern
策略模式… Strategy Pattern 在POS系统中,有时需要实行价格优惠, 该如何处理? 对普通客户或新客户报全价 对老客户统一折扣5% 对大客户统一折扣10% 注:课件 ...
- ES9新内容概括
本文主要介绍ES2018 新出的一些特性 1.异步迭代 允许 async/await 与 for-of 一起使用,以串行的方式运行异步操作,达到异步函数的迭代效果. async function pr ...
- wcf在post请求时,关于string类型参数传入中文的处理
一.方法默认只有一个参数 (1)BodyStyle = WebMessageBodyStyle.Bare [OperationContract][WebInvoke(Method = "PO ...
- docker 容器的mysql主从复制
一. 1.首先拉取docker镜像,我们这里使用5.7版本的mysql: docker pull mysql:5.7 2.分别启动主从两个容器: docker run -p 3339:3306 - ...
- 命令“copy /V 已退出,代码为 1
这个错误出现在vs生成事件里的命令行里. 第一种:简单粗暴直接清空命令行 第二种:通过输出的打印结果来分析: 比如我的出现这个原因一般有两种情况: 第一种:是可能我引用的共享盘Z盘无法连接: 第二种: ...
- awk 中的难懂符号解释
awk中NF和NR的意义,其实你已经知道NF和NR的意义了,NF代表的是一个文本文件中一行(一条记录)中的字段个数,NR代表的是这个文本文件的行数(记录数). 看个例子: cal 9 2003 Sep ...