以下是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值
答案 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段,但从第3段中删除了另一个。该地图从不为空。
我们的Thread现在再次运行,我们查看第2段和第3段,两者都是空的。对我们来说,地图是空的 - 结果。
但是对于任何空槽我们都跟踪它是否被修改过。对于第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(表示:段为空)。或者,换句话说:我们可以确定它一直是空的,因为首先查看已检查的段。