[英]Consistency behaviour of ConcurrentHashMap.keySet().stream()
我可以從這個帶有ConcurrentHashMap
的modify
方法中獲得什么一致性行為?
// map is filled concurrently from multiple threads
private final ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
public void modify(Object newValue) {
map.keySet().stream()
.filter(/* some filter */)
.forEach(k -> {
if (/* k has some property */) {
map.put(k, newValue);
} else {
map.remove(k);
}
});
}
我發現通過閱讀 Javadocs 很難得到明確的答案, keySet()
、 stream()
和 stream 中的 map 條目的修改如何相互作用。 我知道keySet()
的分離器是弱一致的,所以spliterator
至少應該遍歷所有元素,因為它們在過去的某個時候只存在一次。 並發 collections 支持在 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 執行期間修改數據源(請參閱非干擾)。 我總是只修改當前密鑰而不觸及foreach
lambda 中的其他 map 條目,這可能是相關的。
那么上面的代碼是以弱一致的方式“都很好”,還是有一些我應該注意的警告?
注意:上面的代碼也沒有真正的意義,但這是簡化的代碼,省略了其他與並發相關的方面。
使用不同的方法可以更好地編寫代碼,例如 map 本身的forEach
。 如果它增加了答案,請隨時提出改進建議,但請僅提供回答我實際問題的答案。 我不是在問如何讓它變得更好,我只是想知道在我的示例中所有部分如何交互。
stream 至少應該遍歷所有元素,因為它們在過去的某個時候只存在一次
我會從短語中刪除“全部”,因為這個措辭可能會給人一種錯誤的印象,即 stream 會迭代整個ConcurrentHashMap
的一些原子快照。
實際上,stream 可能反映了 map 的(一些)修改,這些修改發生在 stream 創建之后。 因此,ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 發出的第一個和最后一個密鑰可能從未同時出現在 map 中。
弱一致的措辭(由keySet() 的 javadoc引用)提到:
它們[即迭代器和拆分器]保證遍歷元素,因為它們在構造時就存在一次,並且可能(但不保證)反映構造后的任何修改。
在ConcurrentHashMap
的Traverser
的 javadoc (迭代器和拆分器的基本 class)中也提到了它:
封裝了對 containsValue 等方法的遍歷; 還用作其他迭代器和拆分器的基礎 class。
方法提前訪問一次在迭代器構造時可到達的每個仍然有效的節點。 它可能會錯過一些在訪問 bin 后添加到 bin 中的內容,這可以保證一致性。
“過去的某個時間點”也很模糊:您看不到在創建stream()
之前從 map 中刪除的密鑰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.