[英]Is there any reason to use a synchronized HashMap rather than ConcurrentHashMap?
在多線程應用程序中,是否存在在需要時使用帶有同步的 HashMap 比使用 ConcurrentHashMap 更好的場景?
具體來說,我正在考慮一個應用程序,其中地圖初始化如下:
Map<String,String> map = new HashMap<>();
每個線程訪問映射只是為了更新它並立即將其轉換為字符串,因此唯一的同步塊是:
synchronized(map) {
map.put(key,value);
StringBuilder sb = new StringBuilder();
for (String k: map.keySet())
sb.append("("+k+","+map.get(k)+")");
}
在這種情況下,將初始化更改為:
Map<String,String> map = new ConcurrentHashMap<>();
並刪除“同步”?
問題是從應用程序的角度來看什么對您很重要。 如果您希望在 put 方法調用后將映射的字符串轉換與狀態同步,則您的代碼是唯一的解決方案。
如果我們說在您的同步之前地圖的狀態阻止了它:
然后你調用你的一段代碼
key = "key3" and value="value3"
同步塊確保字符串轉換將
(key1,value1)(key2,value2)(key3,value3)
如果您刪除同步塊並將映射更改為某個同步實現,則唯一的同步部分將被放置。 因此,在某些情況下,方法調用的時間線可以是:
所以 Thread1 轉換了錯誤的狀態,因為 Thread2 足夠快,可以在 Thread1 調用字符串轉換之前放置一個新條目。
通常,任何集合的同步實現僅在您希望將集合方法作為原子操作的情況下才有用。 如果您需要在相同的集合狀態下協作更多方法,則必須每次從外部同步它們。
類文檔是這樣說的:
對於諸如 putAll 和 clear 之類的聚合操作,並發檢索可能僅反映某些條目的插入或刪除。 類似地,迭代器、拆分器和枚舉返回反映哈希表在迭代器/枚舉創建時或創建后的某個時刻的狀態的元素。
因此,如果您以原子方式關心這些情況,則可能需要外部同步。
似乎您確實關心這一點,因為您執行keySet()
,這不是原子性的,在執行 for 循環時可能會添加或刪除其他條目
當然。 如果您的使用模式僅在極少數情況下需要同步,那么HashMap
開銷將比ConcurrentHashMap
少。 這是你需要衡量的東西。
當然,除非你正在做一些非常具體和性能密集的事情,否則你在性能方面使用哪一個可能並不重要。 但是,使用ConcurrentHashMap
您不必擔心自己執行synchronization
,因此不會出錯。
一個更直接的問題是是否有任何理由使用Collections.synchronizedMap(new HashMap<>())
而不是ConcurrentHashMap
已經在許多地方討論過,例如: ConcurrentHashMap vs Synchronized HashMap
有趣的是,concurrentHashMap 的性能非常接近非線程安全的 HashMap,並且比同步的 HasHmap 好得多。 所以我不認為同步的 HasHmap 在一般情況下會更好。 https://dzone.com/articles/java-7-hashmap-vs
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.