JDK8的ConcurrentHashMap的初始化源码及注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
private final Node<K,V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { if ((sc = sizeCtl) < 0) Thread.yield(); else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { try { if ((tab = table) == null || tab.length == 0) { int n = (sc > 0) ? sc : DEFAULT_CAPACITY; @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; table = tab = nt; sc = n - (n >>> 2); } } finally { sizeCtl = sc; } break; } } return tab; }
|
由源码可知:初始化的代码比较简单,通过初始化数组,之后将sizeCtl赋值。
这里涉及到的知识点:
- Thread.yield():使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。
- U.compareAndSwapInt(this, SIZECTL, sc, -1)和SIZECTL = U.objectFieldOffset(k.getDeclaredField(“sizeCtl”)):通过反射获取sizeCtl,再通过CAS设置其值。
- sc = n - (n >>> 2):其实就是 0.75 * n,扩容阈值。
这个方法并发通过对SIZECTL+CAS实现。