背景

LongAddr是AtomicLong的增强类,主要用于超高并发情况下的计数问题,建议在超高并发的情况下直接使用该类替代原有的AtomicLong。

实现原理

与ConcurrentHashMap类似,LongAddr主要采用的是分段技术,通过把一个Long拆分为多个Cell,可以大大提高计数时的写入效率。相对的,如果要获取得到的值,则需要所有Cell求和,其效率较普通Long类型更低。总的来说,LongAddr适用于写多读少的高并发场景。

以伪代码形式表示LongAddr的源码逻辑

void add(long val)
    //首先尝试直接将值通过cas的方式写入base中,如果成功则不需要调用cell的逻辑,在低并发情况下就不需要引入cell这种重量级技术
    if (cas(base, base.val, base.val + val)) {
        return;
    } else {
        //尝试将值通过cas方式更新至目标cell中
        if (cas(targetCell, targetCell.val, targetCell.val + val)) {
            return;
        } else {
            //如果未初始化probe参数,则进行初始化
            if (probe == null) {
                initProbe();
            //如果cells[]未初始化,则将整个数组初始化为2,并填入当前target的cell
            } else if (cells == null) {
                cells = new cell[2];
                cell[target] = new Cell();
            //如果cells[target] == null,则需要初始化cells[target]
            } else if (targetCell == null) {
                cell[target] == new Cell();
            //以上都满足,但是仍然cas失败,说明冲突较为密集,对probe所对应的cell进行重新hash
            } else {
                current.probe = probe.newVal;
                reahshFlag = true;
            }
        
            //再次尝试添加至cell中
            if (cas(targetCell, targetCell.val, targetCell.val + val)) {
                return;
            //仍然添加失败,则对cell进行扩容
            } else {
                cells = new cell[cells.length * 2];//扩容的总大小小于CPU数量
            }
        }
    }