首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Java 容器源码分析之ConcurrentHashMap(9)

Java 容器源码分析之ConcurrentHashMap(9)

size实现1.8中使用一个volatile类型的变量baseCount记录元素的个数,当插入新数据或则删除数据时,会通过addCount()方法更新baseCount,实现如下:
if ((as = counterCells) != null ||    !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {    CounterCell a; long v; int m;    boolean uncontended = true;    if (as == null || (m = as.length - 1) < 0 ||        (a = as[ThreadLocalRandom.getProbe() & m]) == null ||        !(uncontended =          U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {        fullAddCount(x, uncontended);        return;    }    if (check <= 1)        return;    s = sumCount();}1、初始化时counterCells为空,在并发量很高时,如果存在两个线程同时执行CAS修改baseCount值,则失败的线程会继续执行方法体中的逻辑,使用CounterCell记录元素个数的变化;
2、如果CounterCell数组counterCells为空,调用fullAddCount()方法进行初始化,并插入对应的记录数,通过CAS设置cellsBusy字段,只有设置成功的线程才能初始化CounterCell数组,实现如下:
else if (cellsBusy == 0 && counterCells == as &&         U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {    boolean init = false;    try {                           // Initialize table        if (counterCells == as) {            CounterCell[] rs = new CounterCell[2];            rs[h & 1] = new CounterCell(x);            counterCells = rs;            init = true;        }    } finally {        cellsBusy = 0;    }    if (init)        break;}3、如果通过CAS设置cellsBusy字段失败的话,则继续尝试通过CAS修改baseCount字段,如果修改baseCount字段成功的话,就退出循环,否则继续循环插入CounterCell对象;
else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))    break;所以在1.8中的size实现比1.7简单多,因为元素个数保存baseCount中,部分元素的变化个数保存在CounterCell数组中,实现如下:
public int size(
) {    long n = sumCount();    return ((n < 0L) ? 0 :            (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :            (int)n);}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;}通过累加baseCount和CounterCell数组中的数量,即可得到元素的总个数;
返回列表