1

以下は、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;
}

編集:ブロックが現在ConcurrentWeakKeyHashMapTest にある場合に上記を評価するコード

基本的に、1つのスレッドがconcurrentMapを継続的に監視し、別のスレッドが同じキーペア値を継続的に追加/削除します

4

2 に答える 2

1

マップが構造的に変更されたことがあるmcsumかどうかをチェックします。変更カウントをゼロにリセットする方法はないようです。そのため、マップに何かが含まれている場合は、mcsumゼロ以外になります。

弱鍵は、マップがput、removeなどによって変更された場合にのみクリーンアップされ、変更されたセグメント内でのみクリーンアップされます。マップから値を取得しても、弱鍵はクリアされません。これは、実装されたマップが、同じセグメントが変更された場合にのみクリーンアップされるため、ガベージコレクションされた多くの弱いキーを保持することを意味します。

これは、メソッドsize()isEmpty()メソッドの結果が頻繁に間違った結果を返すことを意味します。

purgeStaleEntries()提供されているAPIを使用する場合、マップが空かどうかを確認する前に呼び出すのが最善の方法です。

于 2011-08-11T08:22:31.457 に答える
1

このメソッドは、JavasConcurrentHashMapの同じメソッドのコピーです

この種のMap方法では、modCountセグメントごとに、異なるトレッドによって変更されていない場合に操作中に追跡します。マップのトラバース中に、実際にはマップを変更する他の操作が行われる可能性があります。これはABA問題と呼ばれます。マップに空かどうかを尋ねていますが、実際には空ではありませんが、偶然に空になっているようです。簡単な例:

Map with three segements
Segment 1: size=0
Segment 2: size=0
Segment 3: size=1
  1. この瞬間、マップに問い合わせて、空のように見えるセグメント1を調べることにしました。

  2. ここで、別のアルゴリズムが来て、要素をセグメント1に挿入しますが、他の要素をセグメント3から削除します。マップが空になることはありませんでした。

  3. スレッドが再び実行され、セグメント2と3を調べます。どちらも空です。私たちにとって、マップは空です-結果として。

ただし、空のスロットについては、それが変更されたかどうかも追跡しました。そして、スロット3については、変更が加えられていることがわかります。mc[2]>=1つまり、mcsum>=1。これは、建設以来、マップが少なくとも1回変更されたことを意味します。したがって、mcsumの目的に答えるには、次のようにします。これは、デフォルトの空のConcurrentHashMapのショートカットです。変更が一度もなかった場合は、同時変更をチェックする必要はありません。

したがって、何かが起こったことを知っており、各セグメントを再度確認します。セグメントが空の場合、それが何であるかがわかりmodCountます。セグメント3の場合は1でしたが、セグメント1の場合は0でしたmodCount。セグメント1のをチェックすると1になり、count> 0であるため、マップが空ではないことがわかります。

それでも、2番目のループでもABA問題が発生する可能性があります。しかし、modCountsがわかっているので、何かを変更する他の並行アルゴリズムをキャッチできます。したがって、セグメントが空で、modCountで何かが変更された場合、そもそも空ではないと言います。つまり、2番目のループが実行していることです。

お役に立てれば。

編集

そしてもっと重要なのは、どうすれば取得できますか

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

真に評価するには?

これは、セグメントに何かが含まれている場合、または最初のループ以降に何かが変更された場合にtrueと評価されます。また、セグメントに何も含まれておらず、最初のループ以降に何も変更されていない場合は、false(つまり、セグメントが空)と評価されます。または、別の言い方をすれば、最初にチェックされたセグメントを調べてから、常に空になっていることを確認できます。

于 2011-08-11T08:23:42.887 に答える