【本文是为了梳理知识的总结性文章,总结了一些自认为相关的重要知识点,只为巩固记忆以及技术交流,忘批评指正。其中参考了很多前辈的文章,包括图片也是引用,如有冒犯,侵删。】
0 存储结构
从底层实现来看,ConcurrentHashMap和HashMap一样都是数组+链表+红黑树(JDK1.8 为了优化链表查询性能新增红黑树)实现的。
1 类定义
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
implements ConcurrentMap<K,V>, Serializable
2 静态常量
// 最大容量,不能超过该值
private static final int MAXIMUM_CAPACITY = 1 << 30;
// 初始容量,默认是16
private static final int DEFAULT_CAPACITY = 16;
// 最大可能的数组大小
static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 默认支持并发更新的线程数量
private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
// 默认负载因子
private static final float LOAD_FACTOR = 0.75f;
// 同一个桶中链表元素数量超过8可能会转化为树
static final int TREEIFY_THRESHOLD = 8;
// 删除冲突节点后,桶中节点数目小于这个数,红黑树就恢复成链表
static final int UNTREEIFY_THRESHOLD = 6;
// 扩容的临界值
static final int MIN_TREEIFY_CAPACITY = 64;
// 扩容时,并发转移节点(transfer方法)时,每次转移的最小节点数
private static final int MIN_TRANSFER_STRIDE = 16;
// 生成sizeCtl所使用的bit位数
private static int RESIZE_STAMP_BITS = 16;
// 进行扩容所允许的最大线程数
private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1;
// 记录sizeCtl中的大小所需要进行的偏移位数
private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS;
// 以下常量定义了特定节点类hash字段的值
static final int MOVED = -1; // ForwardingNode类对象的hash值
static final int TREEBIN = -2; // TreeBin类对象的hash值
static final int RESERVED = -3; // ReservationNode类对象的hash值
static final int HASH_BITS = 0x7fffffff; /// 普通Node节点的hash初始值
// CPU的数量
static final int NCPU = Runtime.getRuntime().availableProcessors();
// 进行序列化的属性
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("segments", Segment[].class),
new ObjectStreamField("segmentMask", Integer.TYPE),
new ObjectStreamField("segmentShift", Integer.TYPE)
};
3 属性
// 存储元素的数组,其长度必须为2的次方
transient volatile Node<K,V>[] table;
// 扩容时新生成的数组,其大小为原来的两倍
private transient volatile Node<K,V>[] nextTable;
// 基本计数
private transient volatile long baseCount;
//
/**
* Table initialization and resizing control. When negative, the
* table is being initialized or resized: -1 for initialization,
* else -(1 + the number of active resizing threads). Otherwise,
* when table is null, holds the initial table size to use upon
* creation, or 0 for default. After initialization, holds the
* next element count value upon which to resize the table.
*/
// 默认为0,用来控制对表初始化和扩容操作
// sizeCtl = -1,表示正在初始化中
// sizeCtl = -n,表示 n - 1个线程正在进行扩容
// sizeCtl > 0,初始化和扩容中需要使用的容量
// sizeCtl = 0,默认值,使用默认值进行初始化
private transient volatile int sizeCtl;
// 扩容下另一个表的索引
private transient volatile int transferIndex;
// 旋转锁,扩容或者创建counterCells时使用
private transient volatile int cellsBusy;
// counterCell数组
private transient volatile CounterCell[] counterCells;
// 视图