簡體   English   中英

ConcurrentHashMap.keySet().stream() 的一致性行為

[英]Consistency behaviour of ConcurrentHashMap.keySet().stream()

我可以從這個帶有ConcurrentHashMapmodify方法中獲得什么一致性行為?

// 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引用)提到:

它們[即迭代器和拆分器]保證遍歷元素,因為它們在構造時就存在一次,並且可能(但不保證)反映構造后的任何修改。

ConcurrentHashMapTraverser 的 javadoc (迭代器和拆分器的基本 class)中也提到了它:

封裝了對 containsValue 等方法的遍歷; 還用作其他迭代器和拆分器的基礎 class。

方法提前訪問一次在迭代器構造時可到達的每個仍然有效的節點。 它可能會錯過一些在訪問 bin 后添加到 bin 中的內容,這可以保證一致性。

“過去的某個時間點”也很模糊:您看不到在創建stream()之前從 map 中刪除的密鑰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM