以下是 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
此刻,我们决定询问 map 并查看似乎是空的段 1。
现在出现了另一种算法,它会在段 1 中插入一个元素,但会从段 3 中删除另一个元素。Map 从来不为空。
我们的线程现在再次运行,我们查看段 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/