Java ConcurrentWeakKeyHashMap是一种空方法

Java ConcurrentWeakKeyHashMap是一种空方法,java,netty,concurrenthashmap,Java,Netty,Concurrenthashmap,以下是ConcurrentWeakKeyHashMap.java中的isEmpty()方法, 为什么它需要mcsum,if(mcsum!=0){..}块在做什么? public boolean isEmpty() { final Segment<K, V>[] segments = this.segments; /* * We keep track of per-segment modCounts to avoid ABA problems in whic

以下是ConcurrentWeakKeyHashMap.java中的isEmpty()方法,

为什么它需要mcsum,if(mcsum!=0){..}块在做什么?

public boolean isEmpty() {
    final Segment<K, V>[] segments = this.segments;
    /*
     * We keep track of per-segment modCounts to avoid ABA problems in which
     * an element in one segment was added and in another removed during
     * traversal, in which case the table was never actually empty at any
     * point. Note the similar use of modCounts in the size() and
     * containsValue() methods, which are the only other methods also
     * susceptible to ABA problems.
     */
    int[] mc = new int[segments.length];
    int mcsum = 0;
    for (int i = 0; i < segments.length; ++ i) {
        if (segments[i].count != 0) {
            return false;
        } else {
            mcsum += mc[i] = segments[i].modCount;
        }
    }


    // If mcsum happens to be zero, then we know we got a snapshot before
    // any modifications at all were made.  This is probably common enough
    // to bother tracking.
    if (mcsum != 0) {
        for (int i = 0; i < segments.length; ++ i) {
            if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
                return false;
            }
        }
    }


    return true;
}
更重要的是,我如何获得

 if (segments[i].count != 0 || mc[i] != segments[i].modCount) 
是否评估为真?

public boolean isEmpty() {
    final Segment<K, V>[] segments = this.segments;
    /*
     * We keep track of per-segment modCounts to avoid ABA problems in which
     * an element in one segment was added and in another removed during
     * traversal, in which case the table was never actually empty at any
     * point. Note the similar use of modCounts in the size() and
     * containsValue() methods, which are the only other methods also
     * susceptible to ABA problems.
     */
    int[] mc = new int[segments.length];
    int mcsum = 0;
    for (int i = 0; i < segments.length; ++ i) {
        if (segments[i].count != 0) {
            return false;
        } else {
            mcsum += mc[i] = segments[i].modCount;
        }
    }


    // If mcsum happens to be zero, then we know we got a snapshot before
    // any modifications at all were made.  This is probably common enough
    // to bother tracking.
    if (mcsum != 0) {
        for (int i = 0; i < segments.length; ++ i) {
            if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
                return false;
            }
        }
    }


    return true;
}
public boolean isEmpty(){
最终段[]段=本段;
/*
*我们跟踪每段modCounts,以避免ABA问题
*期间,在一个段中添加了一个元素,在另一个段中删除了一个元素
*遍历,在这种情况下,表实际上从来都不是空的
*注意在size()和
*containsValue()方法,这是唯一的其他方法
*易受ABA问题的影响。
*/
int[]mc=新的int[segments.length];
int mcsum=0;
对于(int i=0;i
编辑: 如果块现在处于活动状态,则用于计算上述值的代码


实际上,一个线程持续监视concurrentMap,而另一个线程持续添加/删除相同的密钥对值,
mcsum
检查映射是否在结构上被修改过。似乎无法将修改计数重置为零,因此,如果映射中包含任何内容,则mcsum将不为零

只有通过put、remove、et c更改贴图时,才会清除弱关键点,并且它们仅在修改的段内清除。从映射中检索值不会清除弱键。这意味着实现的映射将包含许多已被垃圾收集的弱密钥,因为只有在修改同一段时才会清除这些弱密钥

这意味着
size()
isEmpty()
方法的结果经常会返回错误的结果


使用提供的API,您最好的方法是在检查映射是否为空之前调用
purgestalentries()

这个方法是Javas中相同方法的副本

这种
Map
在操作过程中使用
modCount
每段跟踪,前提是不同的踏板保持不变。在我们遍历地图的过程中,实际上可能会有其他操作修改地图。这被称为一个。我们在问地图是否是空的,事实上不是,但碰巧它看起来是空的。一个简单的例子:

Map with three segements
Segment 1: size=0
Segment 2: size=0
Segment 3: size=1
  • 在这一刻,我们决定询问地图并查看段1,它似乎是空的

  • 现在出现了另一种算法,将一个元素插入段1,但将另一个元素从段3中删除。地图从来都不是空的

  • 我们的线程现在再次运行,我们查看段2和段3,它们都是空的。对我们来说,地图是空的——因此

  • 但对于任何空插槽,我们也会跟踪它是否被修改。对于插槽3,我们意识到有修改:
    mc[2]>=1
    ,这意味着
    mcsum>=1
    。这意味着:自构建以来,地图至少修改了一次。所以要回答mcsum的用途:它是默认空ConcurrentHashMap的快捷方式。如果从未进行过修改,则不需要检查并发修改

    因此,我们知道发生了什么,并再次检查每个部分。如果现在一个段是空的,我们知道它的
    modCount
    是什么。对于段3,假设它是1,对于段1,它是0。检查段1的
    modCount
    现在为1,并且
    count
    为>0,因此我们知道地图不是空的

    但在第二个循环中也可能存在ABA问题。但是因为我们知道modCounts,所以我们可以捕捉到任何其他并发算法在改变某些东西。所以我们说,如果段是空的,并且modCount发生了变化,那么它一开始就不是空的。也就是说,第二个循环正在做什么

    希望这有帮助

    编辑

    更重要的是,我如何获得

     if (segments[i].count != 0 || mc[i] != segments[i].modCount) 
    
    是否评估为真?

    public boolean isEmpty() {
        final Segment<K, V>[] segments = this.segments;
        /*
         * We keep track of per-segment modCounts to avoid ABA problems in which
         * an element in one segment was added and in another removed during
         * traversal, in which case the table was never actually empty at any
         * point. Note the similar use of modCounts in the size() and
         * containsValue() methods, which are the only other methods also
         * susceptible to ABA problems.
         */
        int[] mc = new int[segments.length];
        int mcsum = 0;
        for (int i = 0; i < segments.length; ++ i) {
            if (segments[i].count != 0) {
                return false;
            } else {
                mcsum += mc[i] = segments[i].modCount;
            }
        }
    
    
        // If mcsum happens to be zero, then we know we got a snapshot before
        // any modifications at all were made.  This is probably common enough
        // to bother tracking.
        if (mcsum != 0) {
            for (int i = 0; i < segments.length; ++ i) {
                if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
                    return false;
                }
            }
        }
    
    
        return true;
    }
    

    如果某个段包含某个内容,或者自第一个循环以来修改了某个内容,则该值为true。如果段不包含任何内容,并且自第一个循环以来没有任何更改,则它的计算结果为false(即:段为空)。或者,换一种说法:我们可以确定,自从第一次查看选中的段以来,它一直是空的。

    感谢您提供的详细答案。现在我只需要拿出一个java代码来测试上面的代码,尝试将上面的if块计算为true对于这个块来说,实际上很简单:只需将一个元素插入到要检查的段中。要测试的代码是: