-
public V put(K key, V value) {
-
Segment<K,V> s;
-
if (value == null)
-
throw new NullPointerException();
-
int hash = hash(key);
-
// hash 值无符号右移 28位(初始化时获得),然后与 segmentMask=15 做与运算
-
// 其实也就是把高4位与segmentMask(1111)做与运算
-
-
// this.segmentMask = ssize - 1;
-
//对hash值进行右移segmentShift位,计算元素对应segment中数组下表的位置
-
//把hash右移segmentShift,相当于只要hash值的高32-segmentShift位,右移的目的是保留了hash值的高位。然后和segmentMask与操作计算元素在segment数组中的下表
-
int j = (hash >>> segmentShift) & segmentMask;
-
//使用unsafe对象获取数组中第j个位置的值,后面加上的是偏移量
-
if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck
-
(segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment
-
// 如果查找到的 Segment 为空,初始化
-
s = ensureSegment(j);
-
//插入segment对象
-
return s.put(key, hash, value, false);
-
}
-
-
/**
-
* Returns the segment for the given index, creating it and
-
* recording in segment table (via CAS) if not already present.
-
*
-
* @param k the index
-
* @return the segment
-
*/
-
@SuppressWarnings("unchecked")
-
private Segment<K,V> ensureSegment(int k) {
-
final Segment<K,V>[] ss = this.segments;
-
long u = (k << SSHIFT) + SBASE; // raw offset
-
Segment<K,V> seg;
-
// 判断 u 位置的 Segment 是否为null
-
if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) == null) {
-
Segment<K,V> proto = ss[0]; // use segment 0 as prototype
-
// 获取0号 segment 里的 HashEntry<K,V> 初始化长度
-
int cap = proto.table.length;
-
// 获取0号 segment 里的 hash 表里的扩容负载因子,所有的 segment 的 loadFactor 是相同的
-
float lf = proto.loadFactor;
-
// 计算扩容阀值
-
int threshold = (int)(cap * lf);
-
// 创建一个 cap 容量的 HashEntry 数组
-
HashEntry<K,V>[] tab = (HashEntry<K,V>[])new HashEntry[cap];
-
if ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u)) == null) { // recheck
-
// 再次检查 u 位置的 Segment 是否为null,因为这时可能有其他线程进行了操作
-
Segment<K,V> s = new Segment<K,V>(lf, threshold, tab);
-
// 自旋检查 u 位置的 Segment 是否为null
-
while ((seg = (Segment<K,V>)UNSAFE.getObjectVolatile(ss, u))
-
== null) {
-
// 使用CAS 赋值,只会成功一次
-
if (UNSAFE.compareAndSwapObject(ss, u, null, seg = s))
-
break;
-
}
-
}
-
}
-
return seg;
-
}
-
-
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
-
// 获取 ReentrantLock 独占锁,获取不到,scanAndLockForPut 获取。
-
HashEntry<K,V> node = tryLock() ? null : scanAndLockForPut(key, hash, value);
-
V oldValue;
-
try {
-
HashEntry<K,V>[] tab = table;
-
// 计算要put的数据位置
-
int index = (tab.length - 1) & hash;
-
// CAS 获取 index 坐标的值
-
HashEntry<K,V> first = entryAt(tab, index);
-
for (HashEntry<K,V> e = first;;) {
-
if (e != null) {
-
// 检查是否 key 已经存在,如果存在,则遍历链表寻找位置,找到后替换 value
-
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 {
-
// first 有值没说明 index 位置已经有值了,有冲突,链表头插法。
-
if (node != null)
-
node.setNext(first);
-
else
-
node = new HashEntry<K,V>(hash, key, value, first);
-
int c = count + 1;
-
// 容量大于扩容阀值,小于最大容量,进行扩容
-
if (c > threshold && tab.length < MAXIMUM_CAPACITY)
-
rehash(node);
-
else
-
// index 位置赋值 node,node 可能是一个元素,也可能是一个链表的表头
-
setEntryAt(tab, index, node);
-
++modCount;
-
count = c;
-
oldValue = null;
-
break;
-
}
-
}
-
} finally {
-
unlock();
-
}
-
return oldValue;
-
}