3

當用於計算的函數在同一映射上調用#computeIfAbsent時,我在併發哈希映射#computeIfAbsent中命中了活鎖條件。併發哈希映射中的活鎖

概念上調用調用看起來像下面

final Map<String, Boolean> map = new ConcurrentHashMap<>(); 
map.computeIfAbsent("k1", k1 -> map.computeIfAbsent("k2", k2 -> Boolean.TRUE)); 

(與CPU之間的單位計算的燒燬3毫秒左右)。不幸的是我不能拿出一個好的單元測試來一致地重現問題。

然而

還有另一種活鎖可能會給你一些線索存在,如果計算函數試圖去除它的調用的關鍵:

final Map<String, Boolean> map = new ConcurrentHashMap<>(); 
map.computeIfAbsent("k", k -> map.remove("k")); 

,而第二個例子是頗爲曲折使用併發哈希映射,它會導致與第一次活動鎖相同的堆棧跟蹤,因此可能會有所幫助。

任何幫助將不勝感激!

+0

[更好的錯誤處理](http://stackoverflow.com/questions/28840047/recursive-concurrenthashmap-computeifabsent-call-never-terminates-bug-or-fea/28845674#28845674)是在Doug的倉庫中,但沒有但在JDK版本中。 –

回答

4

ConcurrentHashMap.computeIfAbsent文件明確指出:當運算正在進行

一些本地圖由其他線程在嘗試更新操作可能會被封鎖,所以在計算應短而簡單,不能嘗試以更新此地圖的任何其他映射

強調我的。內部computeIfAbsent在包含您的密鑰的哈希表條目上進行同步。當您修改碰巧落入當前正在處理的相同條目的另一個鍵時,您可能會遇到意外鎖定。

一般來說,你應該避免這種修改。不幸的是,您沒有爲您的問題提供足夠的背景,所以我不能提出一種替代解決方案。

+0

Doh,我兩次閱讀javadoc並錯過了功能合同。感謝重點! –