ConcurrentWeakKeyHashMap是isEmpty方法

时间:2011-08-11 07:39:00

标签: java netty concurrenthashmap

以下是ConcurrentWeakKeyHashMap.java中的isEmpty()方法, https://github.com/netty/netty/blob/master/src/main/java/org/jboss/netty/util/internal/ConcurrentWeakKeyHashMap.java

为什么需要mcsum,if(mcsum!= 0){..}阻止做什么?

更重要的是,我如何获得

 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;
}

修改 用于评估上述if块的代码现在位于ConcurrentWeakKeyHashMapTest

基本上1个线程连续监视concurrentMap,而另一个线程不断添加/删除相同的keypair值

2 个答案:

答案 0 :(得分:1)

mcsum检查地图是否曾经过结构修改。似乎没有办法将修改计数重置为零,因此如果地图中包含任何内容mcsum将不为零。

仅在通过put,remove和etc更改地图时清除弱键,并且仅在修改的段内清除它们。从地图中检索值不会清除弱键。这意味着实现的地图将包含许多已被垃圾收集的弱密钥,因为只有在修改相同的段时才清理它们。

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

根据提供的API,您最好的办法是在检查地图是否为空之前调用purgeStaleEntries()

答案 1 :(得分:1)

此方法是Javas ConcurrentHashMap中的相同副本。

如果不同的踏板保持不变,这种Map每个段使用modCount来跟踪操作。在我们遍历Map的过程中,实际上可能还有其他操作修改了Map。这称为ABA problem。我们问地图是否为空,事实上它不是,但似乎是偶然的。一个简单的例子:

Map with three segements
Segment 1: size=0
Segment 2: size=0
Segment 3: size=1
  1. 此时我们决定询问地图并查看第1段,该段似乎是空的。

  2. 现在又出现了另一个算法并将一个元素插入到第1段,但从第3段中删除了另一个。该地图从不为空。

  3. 我们的Thread现在再次运行,我们查看第2段和第3段,两者都是空的。对我们来说,地图是空的 - 结果。

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

    所以我们知道发生了什么,并再次检查每个细分。如果现在一个段是空的,我们知道它的modCount是什么。对于段3,假设它为1,对于段1,它为0.检查段1的modCount现在它是1而count是&gt; 0所以我们知道地图不是空的。

    在第二个循环中仍然可能存在ABA问题。但是因为我们知道modCounts,我们可以捕获任何其他并发算法改变一些东西。所以我们说如果段是空的并且某些东西随着modCount而改变,那么它首先不是空的。也就是说,第二个循环正在做什么。

    希望这有帮助。

    修改

      

    更重要的是,我如何获得

    if (segments[i].count != 0 || mc[i] != segments[i].modCount)
    
      

    评估为真?

    如果段包含某些内容或者自第一个循环以来某些内容被修改,则此计算结果为true。并且如果段不包含任何内容并且自第一个循环以来没有任何更改,则计算结果为false(表示:段为空)。或者,换句话说:我们可以确定它一直是空的,因为首先查看已检查的段。