Метод ConcurrentWeakKeyHashMap isEmpty - PullRequest
       8

Метод ConcurrentWeakKeyHashMap isEmpty

1 голос
/ 11 августа 2011

Ниже приведен метод isEmpty () из ConcurrentWeakKeyHashMap.java, 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, в то время как другой поток постоянно добавляет / удаляет тотзначение пары ключей

Ответы [ 2 ]

1 голос
/ 11 августа 2011

Этот метод является его копией в Javas ConcurrentHashMap .

Этот тип 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. Это значит: с момента постройки Карта была изменена хотя бы один раз. Итак, чтобы ответить, для чего предназначен mcsum: это ярлык для пустого ConcurrentHashMap по умолчанию. Если изменений никогда не было, нам не нужно проверять наличие одновременных изменений.

Итак, мы знаем, что что-то случилось, и проверяем снова каждый сегмент. Если сейчас сегмент пуст, мы знаем, что это за modCount. Для сегмента 3 предположим, что это было 1, для сегмента 1 это было 0. Проверка modCount сегмента 1 теперь это 1, а count равно> 0, поэтому мы знаем, что карта не пуста.

Тем не менее, во втором цикле может быть проблема ABA. Но поскольку мы знаем modCounts, мы можем поймать любой другой параллельный алгоритм, который что-то меняет. Таким образом, мы говорим, что если сегмент пуст и что-то изменилось с помощью modCount, он не был пустым. То есть, что делает второй цикл.

Надеюсь, это поможет.

EDIT

И что более важно, как я могу получить

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

, чтобы оценить как истинное?

Это дает значение true, если сегмент содержит что-то или что-то было изменено с момента первого цикла. И оно оценивается как ложное (что означает: сегмент пуст), если сегмент не содержит ничего И ничего не изменилось с момента первого цикла. Или, если сказать по-другому: мы можем быть уверены, что он был пустым все время с тех пор, как впервые посмотрел на проверенный сегмент.

1 голос
/ 11 августа 2011

mcsum проверяет, была ли карта когда-либо структурно модифицирована. По-видимому, нет никакого способа сбросить счетчики модификаций на ноль, поэтому, если карта когда-либо содержала что-либо вообще, mcsum будет отличным от нуля.

Слабые ключи очищаются только тогда, когда карта изменяется с помощью put, remove и т. Д., И они очищаются только в пределах измененного сегмента. Получение значений с карты не устраняет слабые ключи. Это означает, что карта в том виде, в каком она реализована, будет содержать много слабых ключей, которые были собраны сборщиком мусора, поскольку они очищаются только в случае изменения одного и того же сегмента.

Это означает, что результаты методов size() и isEmpty() часто возвращают неверный результат.

Если API предоставлен, лучше всего позвонить по номеру purgeStaleEntries() перед проверкой, пуста ли карта.

...