【问题标题】:’scanAndLockForPut‘ in ConcurrentHashMap JDK1.7ConcurrentHashMap JDK1.7 中的‘scanAndLockForPut’
【发布时间】:2015-07-29 15:02:11
【问题描述】:

我的问题是关于文档中的一句话:

与大多数方法不同,对方法 equals 的调用不会被筛选:由于遍历速度并不重要,我们不妨帮助预热相关代码和访问。

上面这句话我看不懂。具体来说,“未筛选”是什么意思?为什么我们可以“预热相关代码”?

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;

【问题讨论】:

  • 我认为由于锁定保持时间很短,它会在等待而不是锁定时尝试预热缓存,并且可能会发生上下文切换。

标签: java concurrency java.util.concurrent concurrenthashmap


【解决方案1】:

“未筛选”具体是什么意思?

在这种情况下,“筛选”意味着在调用 equals 之前检查身份。以下语句的左侧也取自 CHM:

if ((k = e.key) == key || (e.hash == hash && key.equals(k)))

因此,“未筛选”意味着跳过身份检查。

为什么我们可以“预热相关代码”?

在键上放置和获取使用equals方法来确定匹配,在热身情况下更重要的是确定不匹配的内容,即使您正在筛选身份,也将始终调用equals。如果等待线程都开始调用 key.equals ,这将使其“热”并更快地触发 JIT 编译。更快的 equals 方法意味着在 put 期间持有段锁的时间更少。

还需要注意的是,在 JDK 8 中,这一切都已更改。

【讨论】:

    猜你喜欢
    • 2014-10-01
    • 2013-12-04
    • 2011-02-19
    • 2015-12-17
    • 2013-12-23
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    相关资源
    最近更新 更多