【发布时间】:2017-06-09 14:35:37
【问题描述】:
我观察到 ConcurrentHashMap 已在 Java 8 中完全重写,使其更加“无锁”。我浏览了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;
}
问题:
如何从一个线程查看其他线程对此哈希图所做的修改,因为代码不在同步保护伞下(这将强制执行 happens-before关系)?
注意:整个 ConcurrentHashMap 是一个表的包装器:
transient volatile Node<K,V>[] table;
所以table 是对数组的 volatile 引用,而不是对 volatile 元素数组的引用! 这意味着如果有人更新此数组中的元素,则修改不会在其他线程中可以看到。
【问题讨论】:
-
您可能会发现这是一个(附加的)好读物:javaspecialists.eu/archive/Issue235.html
-
ConcurrentHashMap实际上使用Unsafe从数组元素中执行易失性读取。这就是tabAt方法的作用。 -
澄清一下,@Radiodef
Unsafe的同步在puts 上没有读取。
标签: java concurrency