JDK7中的ConcurrentHashMap代码说明(scanAndLockForPut)

bay*_*amy 5 concurrency concurrenthashmap java.util.concurrent

JDK7中ConcurrentHashMap中的scanAndLockForPut方法的源代码说:

private HashEntry<K,V> scanAndLockForPut(K key, int hash, V value) {
    HashEntry<K,V> first = entryForHash(this, hash);
    HashEntry<K,V> e = first;
    HashEntry<K,V> node = null;
    int retries = -1; // negative while locating node
    while (!tryLock()) {
        HashEntry<K,V> f; // to recheck first below
        if (retries < 0) {
            if (e == null) {
                if (node == null) // speculatively create node
                    node = new HashEntry<K,V>(hash, key, value, null);
                retries = 0;
            }
            else if (key.equals(e.key))
                retries = 0;
            else
                e = e.next;
        }
        else if (++retries > MAX_SCAN_RETRIES) {
            lock();
            break;
        }
        else if ((retries & 1) == 0 &&
                 (f = entryForHash(this, hash)) != first) {
            e = first = f; // re-traverse if entry changed
            retries = -1;
        }
    }
    return node;
}
Run Code Online (Sandbox Code Playgroud)

我了解代码的含义,但如果输入,我不知道这是什么:

else if ((retries & 1) == 0 && (f = entryForHash(this, hash)) != first)
Run Code Online (Sandbox Code Playgroud)

我的问题是: 为什么我们必须做“(重试和1)== 0”?

编辑:我想通了。这是因为常量MAX_SCAN_RETRIES:

static final int MAX_SCAN_RETRIES = Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1;
Run Code Online (Sandbox Code Playgroud)

在单核处理器中,MAX_SCAN_RETRIES =1。因此,线程第二次进入“ while(tryLock)”循环时,不必检查第一个节点是否已更改。

但是,在多核处理器中,这将类似于检查while循环中是否每2次更改第一个节点。

以上解释正确吗?

bay*_*amy 1

我在并发兴趣邮件列表上问过这个问题,作者(Doug Lea)本人回答道:

是的。我们只需要确保最终检测到陈旧性。交替进行头部检查效果很好,并且简化了单处理器和多处理器相同代码的使用。

关联

所以我想这个问题到此就结束了。