查看原文
其他

ConcurrentHashMap之size()方法

2017-11-01 白玉 IT哈哈

 /**
     * 计算map中的key-value对总数
     * 步骤:
     * 1)遍历所有段,计算总的count值sum,计算总的modCount值
     * 2)如果有数据的话(modCount!=0),再遍历所有段一遍,计算总的count值check,在这期间只要有一个段的modCount发生了变化,就再重复如上动作两次
     * 3)若三次后,还未成功,遍历所有Segment,分别加锁(即建立全局锁),然后计算,最后释放所有锁
     */
    public int size() {
        final Segment<K, V>[] segments = this.segments;
        long sum = 0;//总量
        long check = 0;//标志位
        int[] mc = new int[segments.length];//存放每个段的modCount
       
       
        for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
            check = 0;
            sum = 0;//总的count值
            int mcsum = 0;//总的modCount值
            for (int i = 0; i < segments.length; ++i) {//遍历所有段
                sum += segments[i].count;//计算总的count值
                mcsum += mc[i] = segments[i].modCount;//计算总的modCount值
            }
            if (mcsum != 0) {//有数据的话,再检查一遍
                for (int i = 0; i < segments.length; ++i) {
                    check += segments[i].count;//计算总的count
                    if (mc[i] != segments[i].modCount) {//只要有一个段发生了变化(在遍历期间发生了增删变化)
                        check = -1;
                        break;//跳出所有循环
                    }
                }
            }
            if (check == sum)//成功
                break;
        }
        if (check != sum) { //以上三次都为成功的话
            sum = 0;
            //每一个段全部加锁(相当于加了一个全局锁)
            for (int i = 0; i < segments.length; ++i)
                segments[i].lock();
            //进行统计
            for (int i = 0; i < segments.length; ++i)
                sum += segments[i].count;
            //全部解锁
            for (int i = 0; i < segments.length; ++i)
                segments[i].unlock();
        }
        if (sum > Integer.MAX_VALUE)
            return Integer.MAX_VALUE;
        else
            return (int) sum;
    }


在不加锁的情况下遍历所有Segment,读取每个Segment的count和modCount,并进行统计;

完毕后,再遍历一遍所有Segment,比较modCount,是否发生了变化,若发生了变化,则再重复如上动作两次;

若三次后,还未成功,遍历所有Segment,分别加锁(即建立全局锁),然后计算,最后释放所有锁。

注:以如上的方式,大部分情况下,不需要加锁就可以获取size()


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存