【发布时间】:2014-10-01 12:59:08
【问题描述】:
JDK7中ConcurrentHashMap中scanAndLockForPut方法的source codes表示:
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;
}
我理解代码的含义,但我不明白的是 else if 条目:
else if ((retries & 1) == 0 && (f = entryForHash(this, hash)) != first)
我的问题是: 为什么一定要“(retries & 1) == 0”?
编辑: 我有点想通了。这都是因为常量 MAX_SCAN_RETRIES:
static final int MAX_SCAN_RETRIES = Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1;
在单核处理器中,MAX_SCAN_RETRIES = 1。因此线程第二次进入循环“while(tryLock)”时,不必检查第一个节点是否改变。
但是,在多核处理器中,这就像在 while 循环中检查第一个节点是否每 2 次更改一次。
上面的解释对吗?
【问题讨论】:
-
不,你的解释不正确。拥有单个 CPU 内核并不不意味着没有并发性。即使是单核机器也可以进行抢先式多任务处理。根据核心数量做出任何假设都是错误的。顺便说一下,
Runtime.getRuntime().availableProcessors()的结果是允许随时间变化的。见its JavaDoc -
@Holger 是的!我意识到在我发布我的编辑之后,但我决定保持不变。所以如果不是解释,那又是什么呢?
-
我只能猜测,我不想发表猜测。最后,Java 8 的实现看起来完全不同,理解这段特定的代码对我来说并不重要……
标签: concurrency java.util.concurrent concurrenthashmap