java1.8中ConcurrentHashMap

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     }

猜你喜欢

转载自www.cnblogs.com/JMLiu/p/8747834.html
今日推荐