如标题;我认为当不需要get()时unsafe.getObjectVolatile(),并且 volatile 表可以确保线程获取最新的元素
transient volatile Node<K,V>[] table;
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;
}
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);
}
最佳答案
有两个原因:
- 代码没有通过字段
table
访问table
的值 - 相反,引用被复制到名为tab
的本地变量并通过该变量访问。由于该变量不是volatile
(并且局部变量不能是 volatile 的),因此不会授予任何内存模型保证。 volatile
的保证仅在一个线程 A 写入 volatile 变量时才适用;从同一个 volatile 变量读取的其他线程保证可以看到线程 A 所做的所有更改。但是,在这种情况下,变量table
不会频繁更新 - 相反,数组的元素会更新为更新了哪些table
点。但这些元素不是volatile
——事实上,Java 不支持 volatile 数组元素。但是,使用Unsafe.getObjectVolatile
和Unsafe.putObjectVolatile
,当您无法在 Java 中直接声明 volatile 元素数组时,您可以使用 volatile 语义来访问数组元素。这就是这段代码所需要的。
关于java - 并发HashMap有一个 volatile 表,为什么在get()时需要unsafe.getObjectVolatile(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59908363/