IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> concurrentHashMap代码走读 -> 正文阅读

[Java知识库]concurrentHashMap代码走读

这三篇就够了

ConcurrentHashMap的初步使用场景、源码分析讲解(中) - 47号Gamer丶 - 博客园

面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(二) - 掘金

ConcurrentHashMap底层详解(图解扩容)(JDK1.8)_编程芝士的博客-CSDN博客_concurrenthashmap扩容

问 concurrentHashMap 如何确保并发迁移?

? ?数据迁移不停服设计借鉴concurrentHashMap chm _fei33423

ForwardingNode节点

1、标记作用,表示其他线程正在扩容,并且此节点已经扩容完毕
2、关联了nextTable,扩容期间可以通过find方法,访问已经迁移到了nextTable中的数据

nextTable

  • 扩容期间,将table数组中的元素 迁移到 nextTable。即nextTable为创建的新的table,容量为原来的两倍

问 chm 何时会resize?

0.75 等效与 n - n>>2?

?

?首先 s >= (long)(sc = sizeCtl) 此时?sizeCtl=0.75*n .?

ConcurrentHashMap底层详解(图解扩容)(JDK1.8)_编程芝士的博客-CSDN博客_concurrenthashmap扩容
?

sizeCtl

  • 多线程之间,以volatile的方式读取sizeCtl属性,来判断ConcurrentHashMap当前所处的状态。
  • 通过cas设置sizeCtl属性,告知其他线程ConcurrentHashMap的状态变更。

不同状态,sizeCtl所代表的含义也有所不同

  • 未初始化:sizeCtl=0:表示没有指定初始容量。
  • sizeCtl>0:表示初始容量。
  • 初始化中:sizeCtl=-1,标记作用,告知其他线程,正在初始化
  • 正常状态:sizeCtl=0.75n,扩容阈值
  • 扩容中:sizeCtl < 0 : 表示有其他线程正在执行扩容
  • sizeCtl = (resizeStamp(n) << RESIZE_STAMP_SHIFT)+2 表示此时只有一个线程在执行扩容

问 红黑树什么时候转变?

? ?8个的时候,0.75 随机分布,概率很低很低.?

问 ConcurrentHashMap的源码分析-resizeStamp作用?

ConcurrentHashMap的源码分析-resizeStamp_Leon_Jinhai_Sun的博客-CSDN博客

所以resizeStamp(n)的返回值为:高16位置0,第16位为1,低15位存放当前容量n,用于表示是对n的扩容。

1. sizeCtl < 0
已经有线程在扩容,将sizeCtl+1并调用transfer()让当前线程参与扩容。
2.?sizeCtl >= 0
表示没有线程在扩容,使用CAS将sizeCtl的值改为 ( resizeStamp << RESIZE_STAMP_SHIFT) + 2)。rs即resizeStamp(n)

问 chm 会有多个线程同时resize么?

? 因为chm只原表的锁节点,故不同的线程可以同时对不同的分区进行迁移. 只要确保新的table对不同的线程都可见即可.

问 什么时候线程不协助扩容:

如果准备加入扩容的线程,发现以下情况,放弃扩容,直接返回。

a、发现transferIndex=0,即所有node均已分配
b、发现扩容线程已经达到最大扩容线程数

transferIndex 扩容索引

扩容索引,表示已经分配给扩容线程的table数组索引位置。主要用来协调多个线程,并发安全地获取迁移任务(hash桶)。

private transient volatile int transferIndex;
private static final int MIN_TRANSFER_STRIDE = 16; //扩容线程每次最少要迁移16个hash桶

1、在扩容之前,transferIndex 在数组的最右边 。此时有一个线程发现已经到达扩容阈值,准备开始扩容。
2、扩容线程,在迁移数据之前,首先要将transferIndex右移(以CAS的方式修改 transferIndex=transferIndex-stride(要迁移hash桶的个数)),获取迁移任务。每个扩容线程都会通过for循环+CAS的方式设置transferIndex,因此可以确保多线程扩容的并发安全。

换个角度,我们可以将待迁移的table数组,看成一个任务队列,transferIndex看成任务队列的头指针。而扩容线程,就是这个队列的消费者。扩容线程通过CAS设置transferIndex索引的过程,就是消费者从任务队列中获取任务的过程。为了性能考虑,我们当然不会每次只获取一个任务(hash桶),因此ConcurrentHashMap规定,每次至少要获取16个迁移任务(迁移16个hash桶,MIN_TRANSFER_STRIDE = 16)

也就是说transferIndex其实代表当前剩下需要进行扩容的桶的个数。如果transferIndex == 0 那就代表当前没有桶需要进行扩容了。每次一个线程参加扩容transferIndex就需要减MIN_TRANSFER_STRIDE。

问 如何实现同时都要求迁移?

问?tableSizeFor方法??

通过输出可以大致猜到tableSizeFor的作用是返回一个大于输入参数且最小的为2的n次幂的数。dxx??????????????s

即 左零的个数 算出来比较关键. 或者说右移多少位后=0

问 为什么不允许为null?????????

??二义性问题?,对于 ConcurrentHashMap 不允许插入 null 值的问题,有人问过 ConcurrentHashMap 的作者 Doug Lea即getValue=null了,你不知道是key没有,还是真的没有value. 并发需要加锁 containsKey .

问无锁队列?

LMAX Disruptor

问SynchronizedQueue 无锁实现?

增加了线程池3倍性能

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-14 23:36:51  更:2022-04-14 23:43:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:02:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码