Путаница с исходным кодом для метода putVal ConcurrentHashMap - PullRequest
0 голосов
/ 29 ноября 2018

Вот часть кодов для 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 и получает trueA, и B выполняют step2.

enter image description here

из этой ситуации B 'Node заменяет A * Node или сказал A's данные заменены на B, это неправильно.

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

1 Ответ

0 голосов
/ 29 ноября 2018

Вот как реализовано 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 thread , который выполняет compareAndSwapObject first увидит здесь null, а compareAndSwapObject фактически заменит объект , тогда как следующий поток, выполняющий compareAndSwapObject, не изменитзначение, потому что фактическое значение больше не равно нулю, тогда как в качестве условия для изменения значения ожидалось значение null.

...