本文共 1525 字,大约阅读时间需要 5 分钟。
概述:这篇文章包括后面几篇文章是来介绍关于ConcurrentHashMap 1.8的源码结构部分,主要是记录我在学习这个源码的一些知识感悟。
储备知识:
1、 需要了解HashMap的相关源码和结构,可以参照我之前的分析
2、关于红黑树的一些基本知识TreeMap, 也是之前有分析过的
3、一些基础性的概念,CAS, volatile关键字,synchronized关键字,unsafe相关操作,java内存模型。
这里先对这些概念做一个概述,大家能明白这个概念就可以,每个概念展开详细说的话,内容篇幅都会比较长,后面会有日志来专门分析。
java内存模型:关于java内存模型,可以参看下面一张图
每个线程在操作一个变量对象时,都会将对象拷贝一份到工作内存当中,如果工作内存当中的数据没有及时的刷新会主内存,势必会造成多线程情况下的数据不精准问题。所以在多线程情况下,首先要解决的问题就是及时将数据刷新回主内存来保证数据一致性。
volatile关键字
java当中提供的volatile关键字其主要作用就是提供内存可见性。即被其修饰的变量一旦被修改,将会刷新到主内存当中去,如果其他线程在使用这个变量过程中,即使工作内存中也存在这个变量的副本,那么他是会直接放弃工作内存中的拷贝,从主内存当中获取的。
volatile关键字会产生内存屏障,也就意味着,JMM会在这个变量写入之后插入一个内存屏障,在读取之前插入一个内存屏障。也就是线程A修改变量值之后,其他线程都会拿到最新值。
CAS操作
比较然后修改,其使用方式,拿到当前期待值,和内存中的值相比较,如果相同更新为新的数值,如果不相同,则说明其他线程已经修改过该变量,更新失败。整个操作过程是不可分割的。
Unsafe
Unsafe类是java底层提供的,仅供内部使用的一些底层方法,一些常见的方法,objectFieldOffset,获取某个对象的某个字段,相对于对象的地址偏移量,compareAndSwapInt,修改某个对象,指定偏移量的值。
基本数据结构
介绍完基本的一些概念之后,我们从宏观结构角度来看下ConcurrentHashMap1.8的设计方式
这张图很清晰的说明了ConcurrentHashMap的结构,和HashMap1.8还是非常相似的
ConcurrenHashMap中维护了一个数组,Entry<K,V>[] table
而每个table当中的元素是一个链表或者说是红黑树
以上就是他的一个基本数据存储结构。
关键属性介绍
1、capacity是ConcurrentHashMap当中 table数组的长度,必须是2的幂次方,如果是自定义长度的话,也会通过一系列运算转为2次幂,至于为什么,可以参照之前HashMap的分析,这里不做详细介绍
2、load_factor加载因子,capactiy*load_factor用来判断是否需要扩容
3、treeify_threshold = 8 链表长度超过8转为红黑树
4、untreeify_threshold = 6 红黑树长度小于6,从红黑树转为链表
5、sizeCtl 这个字段它的情况比较复杂:
<1>负数表示正在初始化或者扩容操作
<2> -n 表示有n-1个线程正在进行扩容操作
<3>0表示table数组还没有进行初始化
<4>大于0表示扩容的阙值,即size>sizeCtl时进行扩容,等同于hashMap中threshod
6、moved = -1 ,表示当前元素是forwardingNode已经被遍历过,不需要再进行数据调整
以上是ConcurrentHashMap的前期准备内容
参考: