结论:对于链表这种线性数据布局,单线程写且插入操纵保证是后入式的条件下,并发读取是安全的;不会存在误读、链表断开导致的漏读、读到环状链表等标题。 4、如果读取的bin是一个红黑树
====================
说明头节点是个TreeBin节点。
(1)如果正在发生红黑树向链表的untreeify操纵,因为untreeify本身并不粉碎旧的红黑树布局,只是在全部untreeify完成后将头节点一次性替换为新创建的普通Node,可以放心读取。
(2)如果正在发生resize且当前bin正在被transfer,因为transfer本身并不粉碎旧的红黑树布局,只是在全部transfer完成后将头节点一次性替换为ForwardingNode,可以放心读取。
(3)如果其他线程在操纵红黑树,在当前线程遍历红黑树的恣意一个时间点,都大概有单个的其它线程发生add/replace/remove/红黑树的翻转等操纵,参考下面的红黑树的读写锁实现。
TreeBin中的读写锁实现
TreeNode<K,V> root;
volatile TreeNode<K,V> first; volatile Thread waiter; volatile int lockState; // values for lockState
static final int WRITER = 1; // set while holding write lock
static final int WAITER = 2; // set when waiting for write lock
static final int READER = 4; // increment value for setting read lock
private final void lockRoot() { //如果一次性获取写锁失败,进入contendedLock循环体,循环获取写锁或者休眠等待
if (!U.compareAndSetInt(this, LOCKSTATE, 0, WRITER))
contendedLock(); // offload to separate method
} private final void unlockRoot() { lockState = 0;
} //对红黑树加互斥锁,也就是写锁
private final void contendedLock() { boolean waiting = false;
for (int s;