[英]java - volatile semantics in ConcurrentHashMap
在 JDK 8 的ConcurrentHashMap
中,方法tabAt
和setTabAt
用於提供對Node<K,V>[] table
中 bin 的第一個元素的易失性讀/寫。 然而,作者評論說:
請注意,對
setTabAt
的調用始終發生在鎖定區域內,因此原則上只需要發布順序,而不需要完整的 volatile 語義,但目前編碼為 volatile 寫入以保持保守。
我想知道這里的發布順序是否意味着由synchronized
保證的發生前關系(監視器的解鎖發生在同一監視器的每個后續鎖定之前)。 如果是這樣,為什么setTabAt
被認為是保守的,但不是強制性的,因為對tabAt
的調用不僅存在於同步塊內部,而且存在於synchronized
塊之外? 例如:
/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
//...
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable();
// -> tabAt called here, outside the synchronized block
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) {
// -> tabAt called here, inside the synchronized block
if (tabAt(tab, i) == f) {
// do insertion...
}
}
}
}
}
另一個問題是,在上面的代碼中,是否需要在synchronized
塊中調用tabAt
? 據我了解,監視器鎖已經處理了線程之間的 memory 可見性,例如:
synchronized
塊之外調用tabAt
找到的 Node-0 之后setTabAt
)tabAt
(依次調用Unsafe.getObjectVolatile
)來訪問和重新檢查元素。任何幫助將不勝感激。
在 java-8 中,您提到的方法定義為:
static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
}
例如,在 jdk-13 中,它已經是一個release
:
static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
U.putReferenceRelease(tab, ((long)i << ASHIFT) + ABASE, v);
}
而且,據我了解,應該與以下內容一起使用:
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
return (Node<K,V>)U.getReferenceAcquire(tab, ((long)i << ASHIFT) + ABASE);
}
因此,您可以將setTabAt
視為set release
並將tabAt
視為get acquire
。
這里的release
意味着釋放/獲取語義,我在這個答案中談到了這一點。 關鍵是volatile
寫入在某些情況下(順序一致性)“做得太多”,就像這里的情況一樣。
源代碼(jdk-13)中有評論說(關於putReferenceRelease
包括)這是一個“弱(er)易失性”:
putReferenceVolatile 的版本......不保證商店對其他線程的立即可見性......
當讀取線程也使用相同的鎖時, synchronized
部分僅提供 memory 可見性保證; 否則所有賭注都取消。 看來這是您缺少的部分。 這是一個更具描述性的答案,解釋了synchronized
部分如何被嚴重破壞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.