Java程序员都曾被问到的一个问题是:
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
public void remove() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
// table是老数组
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
static final class Segment<K,V> extends ReentrantLock implements Serializable {
}
public V put(K key, V value) {
Segment<K,V> s;
if (value == null)
throw new NullPointerException();
// 根据key的hash再次进行hash运算
int hash = hash(key.hashCode());
// 基于hash定位segment数组的索引。
// hash值是int值,32bits。segmentShift=28,无符号右移28位,剩下高4位,其余补0。
// segmentMask=15,二进制低4位全部是1,所以j相当于hash右移后的低4位。
int j = (hash >>> segmentShift) & segmentMask;
if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck
(segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment
// 找到对应segment
s = ensureSegment(j);
// 调用该segment的put方法,将新节点插入segment中
return s.put(key, hash, value, false);
}
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
// 是否获取锁,失败自旋获取锁(直到成功)
// 拿到结点之后,对结点进行插入操作。
HashEntry<K,V> node = tryLock() ? null :
scanAndLockForPut(key, hash, value);
}
悲观锁:可以完全保证数据的独占性和正确性,因为每次请求都会先对数据进行加锁, 然后进行数据操作,最后再解锁,而加锁释放锁的过程会造成消耗,所以性能不高;
乐观锁:假设没有冲突发生,如果检测到冲突,就失败重试,直到成功。数据库的乐观锁是通过版本控制来实现的。
// 不参与序列化
transient volatile Node<K,V>[] table; // volatile保证线程间可见
// 记录容器的容量大小,通过CAS更新
private transient volatile long baseCount;
/**
* 初始化和扩容控制参数。为负数时表示table正在被初始化或resize:-1(初始化),-(1+扩容线程数)
* sizeCtl默认值为0,大于0是扩容的阀值
*/
private transient volatile int sizeCtl;
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;
// while(true)循环,不断的尝试,因为在table的初始化和casTabAt用到了compareAndSwapInt、compareAndSwapObject
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
// 如果数组(HashMap)还未初始化,进行初始化操作(CAS操作)
if (tab == null || (n = tab.length) == 0)
tab = initTable();
// 计算新插入数据在数组(HashMap)中的位置,如果该位置上的节点为null,直接放入数据(CAS操作)
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
// 如果该节点的hash值为MOVED,说明正在进行扩容操作或者已经扩容
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
//
else {
V oldVal = null;
synchronized (f) {
// 对特定数组节点tab[i]加锁
if (tabAt(tab, i) == f) {
// 判断tab[i]是否有变化
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)))) {
// 如果新插入值和tab[i]处的hash值和key值一样,进行替换
oldVal = e.val;
if (!onlyIfAbsent)
e.val = value;
break;
}
Node<K,V> pred = e;
if ((e = e.next) == null) {
// 如果此节点为尾部节点,把此节点的next引用指向新数据节点
pred.next = new Node<K,V>(hash, key,
value, null);
break;
}
}
}
else if (f instanceof TreeBin) {
// 如果是一颗红黑树
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;
break;
}
}
}
addCount(1L, binCount);
return null;
}