ConcurrentHashMap(Java8)源码分析
1. 常量、成员变量
private static final int MAXIMUM_CAPACITY = 1 << 30; // 和HashMap一样private static final int DEFAULT_CAPACITY = 16; // 和HashMap一样
static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 和HashMap一样
static final int TREEIFY_THRESHOLD = 8; // 和HashMap一样
static final int UNTREEIFY_THRESHOLD = 6; // 和HashMap一样
static final int MIN_TREEIFY_CAPACITY = 64; // 和HashMap一样
private static final float LOAD_FACTOR = 0.75f; // 不怎么用 -> 见transfer方法:sizeCtl = (n << 1) - (n >>> 1)
private static final int DEFAULT_CONCURRENCY_LEVEL = 16; // 旧版的Segment???
private static final int MIN_TRANSFER_STRIDE = 16; // 扩容时最小的迁移分组大小(见transfer)
private static int RESIZE_STAMP_BITS = 16; // 见resizeStamp方法
private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1; // 2^16 - 1
private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS; // 见addCount方法
static final int MOVED = -1; // 转发节点(ForwardingNode)hash
static final int TREEBIN = -2; // 红黑树节点(TreeBin)hash
static final int RESERVED = -3; /// 保留
static final int HASH_BITS = 0x7fffffff; // hash掩码(见spread方法)
static final int NCPU = Runtime.getRuntime().availableProcessors(); // 处理器数量(见transfer方法和fullAddCoun方法)
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("segments", Segment[].class),
new ObjectStreamField("segmentMask", Integer.TYPE),
new ObjectStreamField("segmentShift", Integer.TYPE)
};
transient volatile Node<K,V>[] table; // 哈希数组(链地址法)
private transient volatile Node<K,V>[] nextTable; // 当前扩容时的table(临时)
private transient volatile long baseCount; // 节点基础计数(见addCount方法)
private transient volatile int sizeCtl; // 扩容阈值,类似于HashMap中的threshold
private transient volatile int transferIndex; // 线程迁移bin的起始位置,CAS(transferIndex)成功者可迁移transferIndex前置stride个bin(见transfer)
private transient volatile int cellsBusy; // counterCells锁(见fullAddCount方法)
private transient volatile CounterCell[] counterCells; // baseCount增量(见fullAddCount方法)
private static final sun.misc.Unsafe U;
private static final long SIZECTL;
private static final long TRANSFERINDEX;
private static final long BASECOUNT;
private static final long CELLSBUSY;
private static final long CELLVALUE;
private static final long ABASE;
private static final int ASHIFT;
static {
try {
U = sun.misc.Unsafe.getUnsafe();
Class<?> k = ConcurrentHashMap.class;
SIZECTL = U.objectFieldOffset(k.getDeclaredField("sizeCtl"));
TRANSFERINDEX = U.objectFieldOffset(k.getDeclaredField("transferIndex"));
BASECOUNT = U.objectFieldOffset(k.getDeclaredField("baseCount"));
CELLSBUSY = U.objectFieldOffset(k.getDeclaredField("cellsBusy"));
Class<?> ck = CounterCell.class;
CELLVALUE = U.objectFieldOffset(ck.getDeclaredField("value"));
Class<?> ak = Node[].class;
ABASE = U.arrayBaseOffset(ak); // 数组中存放数据的起始地址(见tabAt方法)
int scale = U.arrayIndexScale(ak); // 数组元素的大小(单位:字节)
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale); // 幂(2^ASHIFT == 1 << ASHIFT == scale),位运算用(见tabAt方法)
} catch (Exception e) {
throw new Error(e);
}
}
2. 获取元素
1' 若key所映射的bin为空,则返回空
2‘ 若当前bin首个节点为待查找节点,则返回首个节点值
3' 若当前bin首个节点哈希值 < 0,则当前bin为红黑树,或当前bin已迁移到新table中
1’‘ 若当前bin为空黑树(TreeBin),则在红黑树上存在写者或等待者时遍历双向链表,否则在红黑树中查找
2'' 若当前bin已迁移到新table中,则根据前进节点(ForwardingNode)前往新table中查找
4' 当前bin首个节点哈希值 >= 0,即当前bin为单向链表,则遍历链表
// 数组内的元素非volatilestatic final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) { // 取table[i]
return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}
public V get(Object key) {
Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
int h = spread(key.hashCode());
if ((tab = table) != null && (n = tab.length) > 0 && (e = tabAt(tab, (n - 1) & h)) != null) { // 当前bin不为空,e头结点
if ((eh = e.hash) == h) { // Node:hash >= 0
if ((ek = e.key) == key || (ek != null && key.equals(ek))) // 头结点为待查找节点
return e.val;
}
else if (eh < 0) // ForwardingNode:MOVED(-1) || TreeBin:TREEBIN(-2)
return (p = e.find(h, key)) != null ? p.val : null; // ForwardingNode.find || TreeNode.find
while ((e = e.next) != null) { // 遍历Node链表
if (e.hash == h && ((ek = e.key) == key || (ek != null && key.equals(ek))))
return e.val;
}
}
return null;
}
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
volatile V val; // volatile
volatile Node<K,V> next; // volatile
Node(int hash, K key, V val, Node<K,V> next);
... ...
}
static final class ForwardingNode<K,V> extends Node<K,V> {
final Node<K,V>[] nextTable;
ForwardingNode(Node<K,V>[] tab); // hash = TREEBIN,设置nextTable
Node<K,V> find(int h, Object k) {
outer: for (Node<K,V>[] tab = nextTable;;) {
Node<K,V> e; int n;
if (k == null || tab == null || (n = tab.length) == 0 || (e = tabAt(tab, (n - 1) & h)) == null) // 当前bin为空
return null;
for (;;) {
int eh; K ek;
if ((eh = e.hash) == h && ((ek = e.key) == k || (ek != null && k.equals(ek)))) // e为待查找节点
return e;
if (eh < 0) { // ForwardingNode:MOVED(-1) || TreeBin:TREEBIN(-2)
if (e instanceof ForwardingNode) { // 继续重定向
tab = ((ForwardingNode<K,V>)e).nextTable;
continue outer;
}
else
return e.find(h, k); // TreeBin.find(红黑树查找)
}
if ((e = e.next) == null) // 遍历Node链表
return null;
}
}
}
}
// 建议自己了解下红黑树和读写锁
static final class TreeBin<K,V> extends Node<K,V> {
TreeNode<K,V> root; // 红黑树根节点
volatile TreeNode<K,V> first; // 双向链表头节点(volatile)
volatile Thread waiter; // 等待者线程
volatile int lockState; // 锁状态(volatile)
static final int WRITER = 1; // 写锁位
static final int WAITER = 2; // 等待位
static final int READER = 4; // 读锁位
TreeBin(TreeNode<K,V> b); // hash = TREEBIN,在TreeNode双向链表上建立红黑树
final Node<K,V> find(int h, Object k) {
if (k != null) {
for (Node<K,V> e = first; e != null; ) {
int s; K ek;
if (((s = lockState) & (WAITER|WRITER)) != 0) { // 存在等待者 || 写者
if (e.hash == h && ((ek = e.key) == k || (ek != null && k.equals(ek)))) // 遍历TreeNode双向链表
return e;
e = e.next;
}
else if (U.compareAndSwapInt(this, LOCKSTATE, s, s + READER)) { // 加读锁(读者++)
TreeNode<K,V> r, p;
try {
p = ((r = root) == null ? null : r.findTreeNode(h, k, null)); // 红黑树查找
} finally {
Thread w;
if (U.getAndAddInt(this, LOCKSTATE, -READER) == (READER|WAITER) && // 释放读锁(读者--):最后一个读者 && 存在等待者
(w = waiter) != null) // 等待者线程不为空
LockSupport.unpark(w); // 唤醒等待者
}
return p;
}
}
}
return null;
}
final TreeNode<K,V> putTreeVal(int h, K k, V v) {
... ...
else {
lockRoot(); // 加写锁
try {
root = balanceInsertion(root, x);
} finally {
unlockRoot(); // 释放写锁
}
}
... ...
}
final boolean removeTreeNode(TreeNode<K,V> p) {
... ...
lockRoot(); // 加写锁
try {
... ...
root = (p.red) ? r : balanceDeletion(r, replacement);
... ...
} finally {
unlockRoot(); // 释放写锁
}
... ...
}
... ...
}
3. 添加元素
1' 若table尚未分配空间,则初始化table
2' 若key所映射的bin为空,则设置首个节点
3' 若table正在进行扩容(首个节点为前进节点),则参与扩容,待扩容完成后再添加新元素
4' 在当前bin上加锁,并在当前bin中插入节点(红黑树 / 单向链表)
5' 节点计数++(可能进行扩容)
// 数组内的元素非volatilestatic final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) { // 置table[i]
U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
}
static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i, Node<K,V> c, Node<K,V> v) { // CAS设置table[i]
return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}
public V put(K key, V value) {
return putVal(key, value, false);
}
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
int binCount = 0; // 添加元素前链表内的元素计数 || 红黑树固定为2
for (Node<K,V>[] tab = table;;) {
// CAS失败 || binCount为0 回到此处
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0) // table尚未分配空间
tab = initTable(); // 为table分配空间
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { // 当前bin为空
if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null))) // CAS设置bin的首个节点
// CAS成功
break;
// CAS失败
}
else if ((fh = f.hash) == MOVED) // f为ForwardingNode类型(f.hash = -1):当前正在扩容,当前bin已迁移至新table中
tab = helpTransfer(tab, f); // 帮助迁移元素
else { // 当前bin不为空
V oldVal = null;
synchronized (f) { // lock当前bin
if (tabAt(tab, i) == f) {
if (fh >= 0) { // 链表
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
K ek;
if (e.hash == hash && ((ek = e.key) == key || (ek != null && key.equals(ek)))) { // 已存在节点
oldVal = e.val;
if (!onlyIfAbsent) // 是否覆盖
e.val = value;
break;
}
Node<K,V> pred = e;
if ((e = e.next) == null) {
pred.next = new Node<K,V>(hash, key, value, null); // 链表尾部添加节点
break;
}
}
}
else if (f instanceof TreeBin) { // 红黑树,f.hash == TREEBIN(-2)
Node<K,V> p;
binCount = 2;
if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key, value)) != null) { // 红黑树添加节点
// 已存在节点
oldVal = p.val;
if (!onlyIfAbsent) // 是否覆盖
p.val = value;
}
}
}
}
if (binCount != 0) {
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i); // 链表转红黑树
if (oldVal != null) // 未添加新的节点
return oldVal; // return 旧值
break;
}
// binCount为0
}
}
addCount(1L, binCount); // 节点计数++,可能进行扩容
return null;
}
private final Node<K,V>[] initTable() {
Node<K,V>[] tab; int sc;
while ((tab = table) == null || tab.length == 0) { // table尚未分配空间
if ((sc = sizeCtl) < 0) /*记录sizeCtl*/
Thread.yield();
else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { /*CAS设置sizeCtl = -1*/
// CAS(sizeCtl)成功
try {
if ((tab = table) == null || tab.length == 0) { // table尚未分配空间
int n = (sc > 0) ? sc : DEFAULT_CAPACITY; // 初始容量保存在sizeCtl中 || 16
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = tab = nt;
sc = n - (n >>> 2); // 计算阈值(容量 * 0.75)
}
} finally {
sizeCtl = sc; // 保存阈值到sizeCtl
}
break;
}
}
return tab;
}
4. 节点计数
增加节点计数(addCount)包含两个步骤:
1' 增加节点计数:基础计数 + 多个增量
2' 扩容:分组迁移节点
public int size() { // 多个线程同步竞争ConcurrentHashMap比较激烈时,size算不准的long n = sumCount();
return ((n < 0L) ? 0 : (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)n);
}
@sun.misc.Contended static final class CounterCell {
volatile long value;
CounterCell(long x) { value = x; }
}
final long sumCount() { // 计算节点总数(baseCount + 各CounterCell.value)
CounterCell[] as = counterCells; CounterCell a;
long sum = baseCount;
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
}
return sum;
}
static final int resizeStamp(int n) {
return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
}
private final void addCount(long x, int check) {
CounterCell[] as; long b, s;
// 若多个线程同步竞争ConcurrentHashMap不激烈,则counterCells可能一直为空
// 若多个线程同步修改ConcurrentHashMap,则一旦出现某个线程CAS(baseCount)失败,将设置counterCells存放baseCount增量if ((as = counterCells) != null || // counterCells不为空
!U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) { // CAS设置baseCount += x(此时baseCount即为节点总数)
// counterCells为空 || CAS(baseCount)失败
CounterCell a; long v; int m;
boolean uncontended = true;
if (as == null || (m = as.length - 1) < 0 || // counterCells为空
(a = as[ThreadLocalRandom.getProbe() & m]) == null || // counterCells当前位置为空
!(uncontended = U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) { // CAS设置CounterCell.value += x
// counterCells为空 || 当前counterCell为空 || CAS(CounterCell.value)失败
fullAddCount(x, uncontended);
return; // 不检查扩容
}
if (check <= 1) // put:check(binCount) <= 1 || remove、clear:check < 0
return; // 不检查扩容
s = sumCount(); // 计算节点总数
}
if (check >= 0) { // put:check(binCount) >= 0
Node<K,V>[] tab, nt; int n, sc;
while (s >= (long)(sc = sizeCtl) // s >= 扩容阈值 /*记录sizeCtl*/
&& (tab = table) != null && (n = tab.length) < MAXIMUM_CAPACITY) {
int rs = resizeStamp(n);
if (sc < 0) { // 正在扩容
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 || sc == rs + MAX_RESIZERS ||
(nt = nextTable) == null || // 扩容尚未准备完成
transferIndex <= 0) // 扩容尚未准备完成 || 扩容完毕
break;
if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) // 参与扩容线程++ /*CAS设置sizeCtl += 1*/
// CAS(sizeCtl)成功
transfer(tab, nt); // helpTransfer to end
}
// 准备扩容(单线程)
else if (U.compareAndSwapInt(this, SIZECTL, sc, (rs << RESIZE_STAMP_SHIFT) + 2)) /*CAS设置sizeCtl = 0x100#####00000000 + 2*/
// CAS(sizeCtl)成功
transfer(tab, null); // 扩容
s = sumCount();
}
}
}
// 本来真的不想看的
private final void fullAddCount(long x, boolean wasUncontended) {
int h;
if ((h = ThreadLocalRandom.getProbe()) == 0) {
ThreadLocalRandom.localInit();
h = ThreadLocalRandom.getProbe();
wasUncontended = true;
}
boolean collide = false;
for (;;) {
CounterCell[] as; CounterCell a; int n; long v;
if ((as = counterCells) != null && (n = as.length) > 0) { // counterCells不为空
if ((a = as[(n - 1) & h]) == null) { // 当前counterCell为空
if (cellsBusy == 0) { // counterCells未加锁 /*确认cellsBusy == 0*/
CounterCell r = new CounterCell(x);
if (cellsBusy == 0 && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { /*CAS设置cellsBusy = 1*///counterCells加锁
// CAS(cellsBusy)成功
boolean created = false;
try {
CounterCell[] rs; int m, j;
if ((rs = counterCells) != null && (m = rs.length) > 0 && rs[j = (m - 1) & h] == null) {
rs[j] = r; // 添加CounterCell
created = true;
}
} finally {
cellsBusy = 0; // counterCells释放锁
}
if (created) // 添加CounterCell成功
break;
continue;
}
}
// 未能添加CounterCell...................................................................................................1
collide = false; // 下次CAS(CounterCell.value)失败不进行扩容
}
else if (!wasUncontended) // 上次CAS(CounterCell.value)失败..................................................................2
wasUncontended = true;
else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x)) // CAS设置CounterCell.value += x............................3
break;
else if (counterCells != as || n >= NCPU) // 已建立新的counterCells || counterCells.length > cup数...........................4
collide = false; // 下次CAS(CounterCell.value)失败不进行扩容
else if (!collide)
collide = true; // 下次CAS(CounterCell.value)失败进行扩容
else if (cellsBusy == 0 && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { // CAS设置cellsBusy = 1(counterCells加锁)
// CAS(cellsBusy)成功
try { // counterCells扩容
if (counterCells == as) {
CounterCell[] rs = new CounterCell[n << 1];
for (int i = 0; i < n; ++i) // 转移CounterCell
rs[i] = as[i];
counterCells = rs;
}
} finally {
cellsBusy = 0; // counterCells释放锁
}
collide = false; // 下次CAS(CounterCell.value)失败不进行扩容
continue; // 再次尝试
}
// 未能添加CounterCell:counterCells已加锁 || CAS(cellsBusy)失败.............................................................1
// 上次CAS(CounterCell.value)失败............................................................................................2
// 本次CAS(CounterCell.value)失败............................................................................................3
// 不进行扩容:已建立新的counterCells || counterCells.length > cup数.........................................................4
// 未能进行counterCells扩容:counterCells已加锁 || CAS(cellsBusy)失败........................................................5
h = ThreadLocalRandom.advanceProbe(h); // 重新计算hash
}
// 当前counterCell为空:CAS设置cellsBusy = 1(counterCells加锁)
else if (cellsBusy == 0 && counterCells == as && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
// CAS(cellsBusy)成功
boolean init = false;
try { // counterCells分配初始空间2
if (counterCells == as) {
CounterCell[] rs = new CounterCell[2];
rs[h & 1] = new CounterCell(x);
counterCells = rs;
init = true;
}
} finally {
cellsBusy = 0; // counterCells释放锁
}
if (init) // 成功分配空间
break;
}
// 当前counterCell为空,counterCells加锁失败:cellsBusy = 1 || CAS(cellsBusy)失败
else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x)) // CAS设置baseCount += x
break;
}
}
5. 扩容
1’ 分组迁移:允许多个线程参与迁移过程
2' 逆序迁移:transferIndex = n -> 0
3' ForwardingNode:对迁移完成的bin,其首个节点设为前进节点
final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {Node<K,V>[] nextTab; int sc;
if (tab != null && (f instanceof ForwardingNode) && // 当前正在扩容
(nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) { // 扩容已准备完毕
int rs = resizeStamp(tab.length);
while (nextTab == nextTable && table == tab && (sc = sizeCtl) < 0) { // 当前正在扩容 /*记录sizeCtl*/
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
sc == rs + MAX_RESIZERS || transferIndex <= 0)
break;
if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) { // 参与扩容线程++ /*CAS设置sizeCtl += 1*/
// CAS(sizeCtl)成功
transfer(tab, nextTab);
break;
}
}
return nextTab;
}
return table;
}
private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {
int n = tab.length, stride;
if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE) // 迁移分组,最小分组为16,最大分组为table容量
stride = MIN_TRANSFER_STRIDE;
if (nextTab == null) { // 准备扩容(单线程)
try {
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1]; // 新的table
nextTab = nt;
} catch (Throwable ex) {
sizeCtl = Integer.MAX_VALUE;
return;
}
nextTable = nextTab;
transferIndex = n; // 当前迁移位置(逆序),transferIndex为0时整个table迁移完毕
}
int nextn = nextTab.length; // n << 1
ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab); // 前进节点 -> 新的table
boolean advance = true;
boolean finishing = false; // 最后一个线程退出扩容,可准备结束
for (int i = 0, bound = 0;;) { // 当前分组的边界[bound, i]
Node<K,V> f; int fh;
while (advance) {
// CAS(transferIndex)失败将回到此处
int nextIndex, nextBound;
if (--i >= bound || finishing) // 当前分组未完全迁移 || 整个table迁移完毕,准备结束
advance = false;
else if ((nextIndex = transferIndex) <= 0) { // 不存在下一个分组 /*记录transferIndex*/
i = -1; // i越界
advance = false;
}
// 计算下个分组的边界:i(nextIndex - 1)和bound(nextBound)
else if (U.compareAndSwapInt(this, TRANSFERINDEX, nextIndex, /*CAS设置transferIndex = nextIndex - stride || 0*/
nextBound = (nextIndex > stride ? nextIndex - stride : 0))) {
// CAS(transferIndex)成功
bound = nextBound; // 高位边界
i = nextIndex - 1; // 低位边界
advance = false;
}
}
// 迁移table[bound ~ i]内的bin(逆序)
if (i < 0 || i >= n || i + n >= nextn) { // i越界检查:所有分组迁移完毕
int sc;
if (finishing) { // 整个table迁移完毕,扩容结束
nextTable = null; // 临时table置空
table = nextTab; // 更换新的table
sizeCtl = (n << 1) - (n >>> 1); // 阈值:0.75 * 容量
return;
}
if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) { // CAS设置sizeCtl -= 1:参与扩容线程--
// CAS(sizeCtl)成功
if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT) // 是否为最后一个退出扩容的线程
return; // 否
// 是
finishing = advance = true; // 准备结束
i = n; // i越界
}
}
else if ((f = tabAt(tab, i)) == null) // 当前bin为空
advance = casTabAt(tab, i, null, fwd); // 置当前节点为重定向节点:可能失败,其它线程在tab[i]处同步添加节点
else if ((fh = f.hash) == MOVED) // 确认当前节点为重定向节点(hash == MOVED):CAS成功 || 迁移当前BIN成功
advance = true; // i++
else { // 当前bin非空:分割、迁移bin
synchronized (f) { // lock当前bin
if (tabAt(tab, i) == f) {
Node<K,V> ln, hn; // 分割后的低位链表(ln)、高位链表(hn)
if (fh >= 0) { // 分割、迁移链表
int runBit = fh & n;
Node<K,V> lastRun = f;
for (Node<K,V> p = f.next; p != null; p = p.next) {
int b = p.hash & n;
if (b != runBit) {
runBit = b;
lastRun = p;
}
}
if (runBit == 0) {
ln = lastRun;
hn = null;
}
else {
hn = lastRun;
ln = null;
}
for (Node<K,V> p = f; p != lastRun; p = p.next) {
int ph = p.hash; K pk = p.key; V pv = p.val;
if ((ph & n) == 0)
ln = new Node<K,V>(ph, pk, pv, ln);
else
hn = new Node<K,V>(ph, pk, pv, hn);
}
setTabAt(nextTab, i, ln);
setTabAt(nextTab, i + n, hn);
setTabAt(tab, i, fwd); // 当前bin迁移完毕,置tab[i]为前进节点
advance = true;
}
else if (f instanceof TreeBin) { // 分割、迁移红黑树
TreeBin<K,V> t = (TreeBin<K,V>)f;
TreeNode<K,V> lo = null, loTail = null; // 低位双向链表
TreeNode<K,V> hi = null, hiTail = null; // 高位双向链表
int lc = 0, hc = 0;
for (Node<K,V> e = t.first; e != null; e = e.next) {
int h = e.hash;
TreeNode<K,V> p = new TreeNode<K,V>(h, e.key, e.val, null, null);
if ((h & n) == 0) {
if ((p.prev = loTail) == null)
lo = p;
else
loTail.next = p;
loTail = p;
++lc;
}
else {
if ((p.prev = hiTail) == null)
hi = p;
else
hiTail.next = p;
hiTail = p;
++hc;
}
}
ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) : // 双向链表转链表
(hc != 0) ? new TreeBin<K,V>(lo) : t; // 在双向链表上建立红黑树(treeify) || noop
hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) : // 双向链表转链表
(lc != 0) ? new TreeBin<K,V>(hi) : t; // 在双向链表上建立红黑树(treeify) || noop
setTabAt(nextTab, i, ln);
setTabAt(nextTab, i + n, hn);
setTabAt(tab, i, fwd); // 当前bin迁移完毕,置tab[i]为前进节点
advance = true;
}
}
}
}
}
}
6. 删除元素
1' 若key所映射的bin为空,则返回
2' 若table正在进行扩容(首个节点为前进节点),则参与扩容,待扩容完成后再删除元素
3' 在当前bin上加锁,并从当前bin中删除节点(红黑树 / 单向链表)
4' 节点计数--
public V remove(Object key) {return replaceNode(key, null, null);
}
final V replaceNode(Object key, V value, Object cv) { // value != null表示替换元素
int hash = spread(key.hashCode());
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0 || (f = tabAt(tab, i = (n - 1) & hash)) == null) // 当前bin为空
break;
else if ((fh = f.hash) == MOVED) // f为ForwardingNode类型(f.hash = -1):当前正在扩容,当前bin已迁移至新table中
tab = helpTransfer(tab, f); // 帮助迁移元素
else { // 当前bin不为空
V oldVal = null;
boolean validated = false;
synchronized (f) { // lock当前bin
if (tabAt(tab, i) == f) {
if (fh >= 0) { // 链表
validated = true;
for (Node<K,V> e = f, pred = null;;) {
K ek;
if (e.hash == hash && ((ek = e.key) == key || (ek != null && key.equals(ek)))) { // 找到待删除(替换)节点
V ev = e.val;
if (cv == null || cv == ev || (ev != null && cv.equals(ev))) {
oldVal = ev;
if (value != null) // 替换元素
e.val = value;
else if (pred != null) // 删除链表的非首个节点
pred.next = e.next;
else // 删除连表的首个节点
setTabAt(tab, i, e.next);
}
break;
}
pred = e;
if ((e = e.next) == null)
break;
}
}
else if (f instanceof TreeBin) { // 红黑树,f.hash == TREEBIN(-2)
validated = true;
TreeBin<K,V> t = (TreeBin<K,V>)f;
TreeNode<K,V> r, p;
if ((r = t.root) != null &&
(p = r.findTreeNode(hash, key, null)) != null) { // 在红黑树中找到待删除(替换)节点p
V pv = p.val;
if (cv == null || cv == pv || (pv != null && cv.equals(pv))) {
oldVal = pv;
if (value != null)
p.val = value;
else if (t.removeTreeNode(p)) // 在红黑树中删除p && 红黑树待转链表
setTabAt(tab, i, untreeify(t.first));
}
}
}
}
}
if (validated) {
if (oldVal != null) { // 存在待删除(替换)节点
if (value == null) // 删除节点而非替换节点值
addCount(-1L, -1); // 节点计数--
return oldVal;
}
break;
}
// 未删除节点
}
}
return null;
}
以上是 ConcurrentHashMap(Java8)源码分析 的全部内容, 来源链接: utcz.com/z/392501.html