----------------------------------------------------------------------------------------------------------

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源码的更多相关文章

  1. JDK1.7 ConcurrentHashMap 源码浅析

    概述 ConcurrentHashMap是HashMap的线程安全版本,使用了分段加锁的方案,在高并发时有比较好的性能. 本文分析JDK1.7中ConcurrentHashMap的实现. 正文 Con ...

  2. Hashtable、ConcurrentHashMap源码分析

    Hashtable.ConcurrentHashMap源码分析 为什么把这两个数据结构对比分析呢,相信大家都明白.首先二者都是线程安全的,但是二者保证线程安全的方式却是不同的.废话不多说了,从源码的角 ...

  3. ConcurrentHashMap源码分析(一)

    本篇博客的目录: 前言 一:ConcurrentHashMap简介 二:ConcurrentHashMap的内部实现 三:总结 前言:HashMap很多人都熟悉吧,它是我们平时编程中高频率出现的一种集 ...

  4. ConcurrentHashMap 源码分析

    ConcurrentHashMap 源码分析 1. 前言    终于到这个类了,其实在前面很过很多次这个类,因为这个类代码量比较大,并且涉及到并发的问题,还有一点就是这个代码有些真的晦涩,不好懂.前前 ...

  5. 死磕 java集合之ConcurrentHashMap源码分析(三)

    本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样 ...

  6. JDK12 concurrenthashmap源码阅读

           本文部分照片和代码分析来自文末参考资料        java8中的concurrenthashmap的方法逻辑和注解有些问题,建议看最新的JDK版本        建议阅读 concu ...

  7. 并发-ConcurrentHashMap源码分析

    ConcurrentHashMap 参考: http://www.cnblogs.com/chengxiao/p/6842045.html https://my.oschina.net/hosee/b ...

  8. 数据结构算法 - ConcurrentHashMap 源码解析

    五个线程同时往 HashMap 中 put 数据会发生什么? ConcurrentHashMap 是怎么保证线程安全的? 在分析 HashMap 源码时还遗留这两个问题,这次我们站在 Java 多线程 ...

  9. ConcurrentHashMap源码走读

    目录 ConcurrentHashMap源码走读 简介 放入数据 容器元素总数更新 容器扩容 协助扩容 遍历 ConcurrentHashMap源码走读 简介 在从JDK8开始,为了提高并发度,Con ...

  10. JDK8中的ConcurrentHashMap源码

    背景 上文JDK8中的HashMap源码写了HashMap,这次写ConcurrentHashMap ConcurrentHashMap源码 /** * Maps the specified key ...

随机推荐

  1. y

    switch(update_state) { : switch(num){ : window.progressn=num $('#h_progress_bar .ui-progress').anima ...

  2. 在IIS中如何配置SSL(https)

    1.打开IIS管理界面>“服务器证书”>“创建自签名证书”>输入名称>点“完成” 2.在“网站”上右键“添加网站”,在“绑定”的“类型”中选择“Https”,在“SSL证书&q ...

  3. linux中的wc命令

    linux中wc命令用法 Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: ...

  4. Web安全测试工具 Burp Suit 使用简介

    参考文档: https://blog.csdn.net/gitchat/article/details/79168613 https://www.cnblogs.com/nieliangcai/p/6 ...

  5. 超详细的java集合讲解

    1 集合 1.1 为什么会出现集合框架 [1] 之前的数组作为容器时,不能自动拓容 [2] 数值在进行添加和删除操作时,需要开发者自己实现添加和删除. 1.2 Collection接口 1.2.1 C ...

  6. C# 指定程序打开指定文件

    Process process = new Process(); process.StartInfo.FileName = 指定程序exe文件路径: process.StartInfo.Argumen ...

  7. [springMvc] 源码分析笔记(一)

    1. Servlet 结构图 2. servlet接口 public interface Servlet { //init方法在容器启动时被容器调用(当load-on-startup设置为负数或者不设 ...

  8. .NET SQLServer数据库转MySql

    第一步:找到下图两个组件,卸载. 第二步:NuGet下载下图组件. 第三步:在连接数据库OnConfiguring方法处,做如下修改: protected override void OnConfig ...

  9. 深入理解CADisplayLink和NSTimer

    一.什么是CADisplayLink 简单地说,它就是一个定时器,每隔几毫秒刷新一次屏幕. CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器.我们在应用中创建一 ...

  10. 基于VC++的网络扫描器设计与实现

    本文正文其实是自己的毕业论文,现在搬上来有两个原因. 一是之前大学的文档都放在百度网盘上,大概去年的时候百度网盘改版搞得不太稳定,文件夹移动次数一多里边就会有一些文件丢失了,也没有很在意.但前几天看申 ...