1. 程式人生 > >java1.8中ConcurrentHashMap

java1.8中ConcurrentHashMap

線程數 .com thread nal spi 參數 不存在 UNC ESS

java1.8中的ConcurrentHashMap做了非常大的改動,整個數據結構都發生了變化,已經不存在segment了。所以要好好重新查看下源碼。這篇博客是逐步更行的,看一點寫一點。

首先看一個很重要的參數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倍。

 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 }

java1.8中ConcurrentHashMap