java - ConcurrentWeakKeyHashMap isEmpty 方法

标签 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) {..} block 做什么?

更重要的是,我如何获得

 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 block 现在位于 ConcurrentWeakKeyHashMapTest 的代码

本质上,1个线程持续监视并发映射,而另一个线程不断添加/删除相同的 key 对值

最佳答案

此方法是 Java 中相同方法的副本 ConcurrentHashMap .

这种Map使用每个段的modCount来跟踪操作期间它是否在不同的步数中保持不变。在我们遍历 Map 的过程中,实际上可能还有其他操作修改 Map。这称为 ABA problem 。我们询问 map 是否为空,事实上它不是,但偶然它看起来是空的。一个简单的例子:

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

  2. 现在出现了另一种算法,它会在段 1 中插入一个元素,但会从段 3 中删除另一个元素。Map 从来不为空。

  3. 我们的线程现在再次运行,我们查看段 2 和 3,两者都是空的。对于我们来说, map 是空的 - 因此。

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

所以我们知道发生了一些事情并再次检查每个片段。如果现在一个段是空的,我们就知道它的 modCount 是多少。对于段 3,假设它是 1,对于段 1,它一直是 0。检查段 1 的 modCount,现在它是 1,并且 count > 0,所以我们知道 Map 不是空的。

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

希望这有帮助。

编辑

And more importantly, how do I get

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

to evaluate to true?

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

关于java - ConcurrentWeakKeyHashMap isEmpty 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7022428/

相关文章:

java - 关于布局管理器使用的困惑

java - 每个固定时间间隔更新 session 属性。 Java、Servlet、JSP

java - 我正在尝试连接我的jdbc程序oracle数据库10g并使用window 8

java - 为什么ConcurrentHashMap在1.8中用0x7fffffff计算hashcode?

java - 当两个线程同时执行cache.putIfAbsent时会发生什么?

java - 在 JUnit 测试中处理 System.exit(0)

java - Netty 不会写

java - 使用 Netty 的聊天服务器

java - 无法在 netty 中连接 ssl

java - 拆分不同范围内的数字