java1.8中的ConcurrentHashMap作了很是大的改動,整個數據結構都發生了變化,已經不存在segment了。因此要好好從新查看下源碼。這篇博客是逐步更行的,看一點寫一點。java
首先看一個很重要的參數sizeCtl,這是一個volatile變量,從名字就能夠看出,這是一個大小控制參數。這個參數當CHM的table正在被某個線程正在初始化或者正在resize的時候是負數。當在初始化的時候,是-1;當在resize的時候,值是1(1+正在執行resize操做的線程數量)。在table初始化以前,它是0,初始化以後的其餘時間它是下一次table要變成的大小。好神奇有用的一個參數啊。數據結構
private transient volatile int sizeCtl;
接下來看initTable函數。這個函數只有在第一次執行普通操做是纔會調用。這個函數第一次展現了sizeCtl的威力。當sizeCtl小於0時,說明有其餘線程正在初始化table或者resize table,則主動放棄線程。函數
不然經過CAS把sizeCtl置爲-1,這樣其餘線程在initTable完成以前,看到的sizeCtl都是-1。而後初始化table,而且sizeCtl置爲原來(DEFAULT_CAPACITY,爲16)的2倍。this
1 private final Node<K,V>[] initTable() { 2 Node<K,V>[] tab; int sc; 3 while ((tab = table) == null || tab.length == 0) { 4 if ((sc = sizeCtl) < 0) 5 Thread.yield(); // lost initialization race; just spin 6 else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { 7 try { 8 if ((tab = table) == null || tab.length == 0) { 9 int n = (sc > 0) ? sc : DEFAULT_CAPACITY; 10 @SuppressWarnings("unchecked") 11 Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n]; 12 table = tab = nt; 13 sc = n - (n >>> 2); 14 } 15 } finally { 16 sizeCtl = sc; 17 } 18 break; 19 } 20 } 21 return tab; 22 }