【引言】ConcurrentHashMap,从名字上来看呢,是Concurrent和HashMap的结合体,实际就是线程安全的HashMap了,但是它如何实现这个线程安全呢?和Hashtable又有何区别呢?这里面就有的说道说道了。
类的定义
1 | /** |
重要常量
1 | /* ---------------- Constants -------------- */ |
成员变量
1 | /** |
构造方法
ConcurrentHashMap()
1 | // 【Lin.C】:默认构造方法,没啥好说的,就是个空方法 |
ConcurrentHashMap(int initialCapacity)
1 | // 【Lin.C】:根据指定大小初始化 |
ConcurrentHashMap(Map<? extends K, ? extends V> m)
1 | // 【Lin.C】:通过别的Map构造的话,就是putAll的过程 |
ConcurrentHashMap(int initialCapacity, float loadFactor)
1 | // 【Lin.C】:调的构造方法5 |
ConcurrentHashMap(…3params)
1 | // 【Lin.C】:带初始化大小,带负载因子,带预估的并发线程数 |
初始化
initTable
1 | /** |
增
put
1 | /** |
删
remove
1 | /** |
改
查
扩容
helpTransfer
1 | /** |
transfer
1 | /** |
addCount
1 | /** |
put
1 | /** |
其他方法
spread
1 | // 【Lin.C】:hash扰动函数,跟1.8的HashMap的基本一样,& HASH_BITS用于把hash值转化为正数,负数hash是有特别的作用的 |
tableSizeFor
1 | // 【Lin.C】:用于求2^n,用来作为table数组的容量,同1.8的HashMap |
comparableClassFor
1 | // 【Lin.C】:1.8的HashMap中讲解红黑树相关的时候说过,用于获取Comparable接口中的泛型类 |
compareComparables
1 | // 【Lin.C】:同1.8的HashMap,当类型相同且实现Comparable时,调用compareTo比较大小 |
from Unsafe
1 | // 【Lin.C】:下面几个用于读写table数组,使用Unsafe提供的更强的功能(数组元素的volatile读写,CAS 更新)代替普通的读写,调用者预先进行参数控制 |
treeifyBin
1 | // 【Lin.C】:满足变换为红黑树的两个条件时(链表长度这个条件调用者保证,这里只验证Map容量这个条件),将链表变为红黑树,否则只是进行一次扩容操作 |
untreeify
1 | // 【Lin.C】:规模不足时把红黑树转化为链表,此方法由调用者进行synchronized加锁,所以这里不加锁 |
内部类
Node
1 | /** |
TreeNode
1 | /** |
ForwardingNode
1 | /** |
TreeBin
1 |
|
ReservationNode
1 | /** |
关于sizeCtl
在扩容操作中有个关键的变量sizeCtl,实际上该变量高 16 位保存 length 生成的标识符,低 16 位保存并发扩容的线程数