sizectl в concurrentHashMap в java8 - PullRequest
       8

sizectl в concurrentHashMap в java8

0 голосов
/ 26 августа 2018

Поскольку я читаю исходный код concurrentHashMap в java8, меня немного смущает переменная sizeCtl, она говорит

При отрицательном значении таблица инициализируется или изменяется: -1 для инициализации, иначе - (1 + количество активных потоков с изменяющимся размером)

Но в исходном коде он будет использовать U.compareAndSetInt(this, SIZECTL, sc, sc + 1) при попытке изменить размер ConcurrentHashMap и использовать U.compareAndSetInt(this, SIZECTL, sc = sizeCtl, sc - 1) после завершения операции.

Эти операции меня смущают, например, если одновременно происходит изменение размера карты двумя потоками, то sizeCtl равно -3, однако, когда новый поток пытается помочь изменить размер, sizeCtl должно быть -4 в соответствии с описанием комментария выше, но, похоже, -2 в соответствии с кодом U.compareAndSetInt(this, SIZECTL, sc, sc + 1).

final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {
    Node<K,V>[] nextTab; int sc;
    if (tab != null && (f instanceof ForwardingNode) &&
        (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
        int rs = resizeStamp(tab.length);
        while (nextTab == nextTable && table == tab &&
               (sc = sizeCtl) < 0) {
            if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
                sc == rs + MAX_RESIZERS || transferIndex <= 0)
                break;
            if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
                transfer(tab, nextTab);
                break;
            }
        }
        return nextTab;
    }
    return table;
}

1 Ответ

0 голосов
/ 05 октября 2018

Мне показалось, что это неверно.

При отрицательном значении таблица инициализируется или изменяется: -1 для инициализации, иначе - (1 + количество активных потоков с изменяемым размером)

Так как первый поток, который входит в функцию transfer, устанавливает sizeCtl в (resizeStamp(tab.length) << RESIZE_STAMP_SHIFT) + 2.Это минус, абсолютная ценность которого очень велика.Это sizeCtl увеличивает 1, когда каждый поток входит в функцию, а затем вычитает 1, прежде чем каждый поток выходит из функции.

while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
               (n = tab.length) < MAXIMUM_CAPACITY) {
            int rs = resizeStamp(n);
            if (sc < 0) {
                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
                    sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
                    transferIndex <= 0)
                    break;
                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
                    transfer(tab, nt);
            }
            else if (U.compareAndSwapInt(this, SIZECTL, sc,
                                         (rs << RESIZE_STAMP_SHIFT) + 2))
                transfer(tab, null);
            s = sumCount();
        }

Это мои мысли, но я не уверен.

...