先撸源码直接了当
// Original (since JDK1.2) Map methods /** * {@inheritDoc} */ public int size() { long n = sumCount(); return ((n < 0L) ? 0 : (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)n); }
这里有个 sumCount()方法
final long sumCount() { CounterCell[] as = counterCells; CounterCell a; long sum = baseCount; if (as != null) { for (int i = 0; i < as.length; ++i) { if ((a = as[i]) != null) sum += a.value; } } return sum; }
原来看的时候一看见for循环 和 sum+= 就以为就这样了。图样图森破!!!!!
今天看 LongAdder 发现错了 。。。
先接着看ConcurrentHashMap 的这个内部类 CounterCell
/* ---------------- Counter support -------------- */ /** * A padded cell for distributing counts. Adapted from LongAdder * and Striped64. See their internal docs for explanation. */ @sun.misc.Contended static final class CounterCell { volatile long value; CounterCell(long x) { value = x; } }
Cell
类是 Striped64
的静态内部类。通过注解 @sun.misc.Contended
来自动实现缓存行填充,让Java编译器和JRE运行时来决定如何填充。本质上是一个填充了的、提供了CAS更新的volatile变量。
翻译下注释:
一种用于分配计数的填充单元。改编自LongAdder和Striped64。请查看他们的内部文档进行解释。
LongAdder 和 Striped64 其实都是分片计算部分,简单理解
我们可以看到Cell类的内部是一个volatile的变量,然后更改这个变量唯一的方式通过cas。我们可以猜测到LongAdder的高明之处可能在于将之前单个节点的并发分散到各个节点的,这样从而提高在高并发时候的效率。
这是Striped64可以继续延伸阅读
http://ifeve.com/java8-striped64-and-longadder/