为什么 JDK11 的 ConcurrentHashMap 不需要 tabAt 和 setTabAt 方法中的 volatile 语义?

问题描述 投票:0回答:0

在JDK8的

ConcurrentHashMap
中,
tabAt
setTabAt
这两个方法都需要volatile语义。

static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
    return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}

static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
    U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
}

作者评论说:

Note that calls to setTabAt always occur within locked regions, 
and so in principle require only release ordering, 
not full volatile semantics, 
but are currently coded as volatile writes to be conservative.

那么在JDK11的

ConcurrentHashMap
中,
tabAt
setTabAt
这两个方法都不需要volatile语义,而是使用acquire和release语义。

static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
    return (Node<K,V>)U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE);
}

static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
    U.putObjectRelease(tab, ((long)i << ASHIFT) + ABASE, v);
}

作者评论说:

Note that calls to setTabAt always occur within locked regions, 
and so require only release ordering.

据我所知,数组

Node<K,V>[] tab
的元素不是
volatile
。仅使用获取和释放语义不能保证可见性。获取元素的线程不能立即看到设置元素的线程所做的更新。

即使对

setTabAt
的调用总是发生在锁定区域内,似乎也没有任何区别。因为对
tabAt
的调用并不总是发生在锁定区域内,所以没有 happends-before 关系。

tabAt
的调用不在方法的锁定区域内发生
get

    public V get(Object key) {
        Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
        int h = spread(key.hashCode());
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (e = tabAt(tab, (n - 1) & h)) != null) {
            if ((eh = e.hash) == h) {
                if ((ek = e.key) == key || (ek != null && key.equals(ek)))
                    return e.val;
            }
            else if (eh < 0)
                return (p = e.find(h, key)) != null ? p.val : null;
            while ((e = e.next) != null) {
                if (e.hash == h &&
                    ((ek = e.key) == key || (ek != null && key.equals(ek))))
                    return e.val;
            }
        }
        return null;
    }

不知道是不是我的理解有问题。谁能提供更多相关信息?

任何帮助将不胜感激。

java volatile concurrenthashmap
© www.soinside.com 2019 - 2024. All rights reserved.