Segment(float lf, int threshold, ConcurrentHashMap.HashEntry<K,V>[] tab) {
this.loadFactor = lf;
this.threshold = threshold;
this.table = tab;
}
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
// tryLock通过无锁cas操作尝试获取锁(无等待), 继承自ReentrantLock.
// 如果成功则, node = null
// 如果不成功, 则可能其他线程已经在插入数据了,
// 此时会尝试继续获取锁tryLock, 自旋MAX_SCAN_RETRIES次, 若还是拿不到锁才开始lock
ConcurrentHashMap.HashEntry<K,V> node = tryLock() ? null :
scanAndLockForPut(key, hash, value);
V oldValue;
try {
ConcurrentHashMap.HashEntry<K,V>[] tab = table;
// 获取分区中哪一个entry链的index
int index = (tab.length - 1) & hash;
// 获取第一个entry
ConcurrentHashMap.HashEntry<K,V> first = entryAt(tab, index);
for (ConcurrentHashMap.HashEntry<K,V> e = first;;) {
// e != null , 存在hash冲突, 把他加到当前链表中
if (e != null) {
K k;
if ((k = e.key) == key ||
(e.hash == hash && key.equals(k))) {
oldValue = e.value;
if (!onlyIfAbsent) {
e.value = value;
++modCount;
}
break;
}
e = e.next;
}
else {
// 无hash冲突, new entry
if (node != null)
node.setNext(first);
else
node = new ConcurrentHashMap.HashEntry<K,V>(hash, key, value, first);
int c = count + 1;
// 空间大小超出阈值, 需要rehash, 翻倍空间.
if (c > threshold && tab.length < MAXIMUM_CAPACITY)
rehash(node);
else
//放到分区中
setEntryAt(tab, index, node);
++modCount;
count = c;
oldValue = null;
break;
}
}
} finally {
unlock();
}
return oldValue;
}
阻塞队列, 主要用于多线程之间共享数据.
当一个线程读取数据时, 如果队列是空的, 则当前线程会进入等待状态.
如果队列满了, 当一个线程尝试写入数据时, 同样会进入等待状态.
适用于生产消费者模型.
其源码实现也相对简单.