Путаница в исходном коде метода putVal ConcurrentHashMap

Вот часть кодов для метода putVal:

final V putVal(K key, V value, boolean onlyIfAbsent) {
    if (key == null || value == null) throw new NullPointerException();
    int hash = spread(key.hashCode());
    int binCount = 0;
    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        if (tab == null || (n = tab.length) == 0)
            tab = initTable();  // lazy Initialization
        //step1,tabAt(...) is CAS
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            //step2,casTabAt(...) is CAS
            if (casTabAt(tab, i, null,
                         new Node<K,V>(hash, key, value, null)))
                break;                   // no lock when adding to empty bin
        }
       ...
    return null;
}  

Предположим, что в настоящее время существует два потока, A и B, и когда A выполняет step1, он получает true, но в то же время B также выполняет step1 и также получает true. И A, и B выполняют step2.

Путаница в исходном коде метода putVal ConcurrentHashMap

в этой ситуации BNode заменяет ANode, или данные A заменяются на B, это неверно.

Я не знаю, правильно это или неправильно, может ли кто-нибудь помочь мне решить эту проблему?

Не могли бы вы дать ссылку на полный исходный код?

Ellen Spertus 29.11.2018 11:38

Вот исходный код

JerryLin 29.11.2018 11:56
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
124
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот как реализован casTabAt:

static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                    Node<K,V> c, Node<K,V> v) {
    return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}

Тогда как U заявлен следующим образом: private static final sun.misc.Unsafe U;. Методы этого класса гарантирует атомарность на низком уровне. И из этого использования:

casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null))

мы можем видеть, если предположить, что третий параметр compareAndSwapObject является ожидаемым значением, то, из-за гарантированной атомарности, поток A или Bкоторый сначала выполняет compareAndSwapObject увидит здесь null и compareAndSwapObjectфактически заменит объект, тогда как следующий поток, выполняющий compareAndSwapObject, не изменит значение, потому что фактическое значение больше не является нулевым, тогда как нулевое значение ожидалось как условие для изменения значения.

да, я знаю это, поэтому в этом случае это означает, что поток B не будет помещать значение в ConcurrentHashMap

JerryLin 29.11.2018 13:00

Собственно нет: compareAndSwapObject, так же как и catTabAt возвращает истину, если замена была произведена. И учитывая, что if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null))) break; не будет вызывать break (потому что для второй операции записи он вернет false), цикл верхнего уровня (for (Node<K,V>[] tab = table;;) {...}) просто запустится еще раз.

nyarian 29.11.2018 13:09

Всегда добро пожаловать :) Если я вам помог - не забудьте отметить ответ как принятый.

nyarian 29.11.2018 13:13

Другие вопросы по теме