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 ...
随机推荐
- 大数据Hadoop——HDFS Shell操作
一.查询目录下的文件 1.查询根目录下的文件 Hadoop fs -ls / 2.查询文件夹下的文件 Hadoop fs -ls /input 二.创建文件夹 hadoop fs -mkdir /文件 ...
- vue history模式
注意: 1.前端:config.js路径问题 2.后台:配置nginx
- BeanNameAware和BeanFactoryAware接口
平时写代码很少去实现这两个接口,这里只是做下了解,方便读Spring源码.BeanNameAware接口作用:让Bean对Name或id有知觉 package com.example.demo.biz ...
- Django web框架-----win10搭建django2.1.7开发环境,定义简易视图及网址
① 安装Django 使用pip命令或者pycharm setting的project Interpreter工具添加安装 检查是否安装成功,以下命令无报错即成功: 查看安装的Django版本号的两种 ...
- JMETER-02
JMeter使用篇 1.界面介绍 2.JMeter-测试计划 测试计划:一个JMeter脚本只有一个测试计划,且测试计划必须启用状态 容易掉的坑:由于JMeter脚本中的每个元器件都可以单独禁用,上级 ...
- 如何在hadoop上做等频离散化
抛砖引玉,先根据特征值group by,统计每个特征值出现次数,然后reduce到一个文件,根据一个文件来统计吧,毕竟,你知道多个桶,那么每个桶多少个样本就是确定了,数数,数到一个桶样本的时候停止,就 ...
- hive -- 分区,分桶(创建,修改,删除)
hive -- 分区,分桶(创建,修改,删除) 分区: 静态创建分区: 1. 数据: john doe 10000.0 mary smith 8000.0 todd jones 7000.0 boss ...
- Redhat 6.3上安装libssh
遇到了很多坑,决定记录下来,有些经验还是很有帮助的. 最重要的一条就是:安装rpm包,总是比编译源码安装(make&make install)更快.记住两个rpm网站:https://pkgs ...
- JeasyUI,导出Excel
这个是客户端表格导出伪Excel文档. 不知道为啥,超过200条,不能导出,显示网络错误 $.extend($.fn.datagrid.methods, { //超过200条,不能导出,显示网络错误? ...
- onceAgain, 这是一个py群的群公告说明
群规: 1. 不骚扰人 2. 不涉及娱乐政治 3. 主要就这两条 入门参考:https://book.douban.com/review/9547077/ qq群/网盘:523445644 # 加群 ...