数据结构
由 Segment数组 + HashEntry 数组 构成 HashEntry 存键值对
一个concurrentHashMap 饱和Segment数组
一个Segmengt包含一个HashEntry数组
一个HashEntry元素是一个链表
锁的获取时在 segment 上的竞争
图示:
HashEntry
static final class HashEntry<K,V> {
final int hash;
final K key;
volatile V value;
volatile HashEntry<K,V> next;
HashEntry(int hash, K key, V value, HashEntry<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
put操作
public V put(K key, V value) {
Segment<K,V> s;
if (value == null)
throw new NullPointerException();
int hash = hash(key);
// 通过位运算确定哪个segment,
int j = (hash >>> segmentShift) & segmentMask;
// 通过unsafe 获取
if ((s = (Segment<K,V>)UNSAFE.getObject
(segments, (j << SSHIFT) + SBASE)) == null)
s = ensureSegment(j);//初始化一个segment
//调用Segment的put方法
return s.put(key, hash, value, false);
}
- 先算hash
- 确定segment的下表
-
Segment的put方法
```java final V put(K key, int hash, V value, boolean onlyIfAbsent) { //对segment加锁 HashEntry
node = tryLock() ? null : scanAndLockForPut(key, hash, value);
V oldValue; try {
//
HashEntry<K,V>[] tab = table;
int index = (tab.length - 1) & hash;
//获取头结点
HashEntry<K,V> first = entryAt(tab, index);
for (HashEntry<K,V> e = first;;) {//开始遍历first为头结点的链表
if (e != null) {//<1>
//
//依据onlyIfAbsent来判断是否覆盖已有的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;//说明当前e节点对应的key不是需要的
}
else {//头插法
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)//判断是否需要进行扩容
//扩容,node插入到新的数组中。
rehash(node);
else
setEntryAt(tab, index, node);
++modCount;
count = c;
oldValue = null;
break;
}
}
} finally {
unlock();
} return oldValue; }
```
- 先获取segment的锁
- 找到k所在HashEntry 数组的下表
- 获取这个HashEntry 的头节点
- 开始遍历
- 采用头插法