![](/img/trans.png)
[英]Java concurrency using ConcurrentHashMap with synchronized block
[英]Does a ConcurrentHashMap need to be wrapped in a synchronized block?
對ConcurrentHashMap( put()
, remove()
等)的所有非retreival操作是否需要包裝在synchronized(this)
塊中? 我知道所有這些操作都是線程安全的,所以這樣做有什么好處/需要嗎? 使用的唯一操作是put()
和remove()
。
protected final Map<String, String> mapDataStore = new ConcurrentHashMap<String, String>();
public void updateDataStore(final String key, final String value) {
...
synchronized (this) {
mapDataStore.put(key, value);
}
...
}
不,你這樣做會失去ConcurrentHashMap
的好處。 您也可以使用帶有synchronized
或synchronizedMap()
的HashMap
來鎖定整個表(這是您在synchronized
包裝操作時所執行的操作,因為監視器隱含的是整個對象實例。)
ConcurrentHashMap
的目的是通過允許對表進行並發讀/寫而不鎖定整個表來增加並發代碼的吞吐量。 該表通過使用鎖定條帶內部支持這一點(多個鎖而不是一個,每個鎖分配給一組散列桶 - 參見Goetz等人的Java Concurrency in Practice )。
一旦你使用ConcurrentHashMap
,所有標准的map方法( put()
, remove()
等)都會因為實現中的鎖條帶等而變為原子。 唯一的權衡是像size()
和isEmpty()
這樣的方法可能不一定會返回准確的結果,因為它們可能是所有操作鎖定整個表的唯一方法。
ConcurrentMap
接口接口還添加了新的原子復合操作,如putIfAbsent()
(僅當鍵不在映射中時才放置東西), remove()
接受鍵和值(僅當條目的值等於參數時才刪除條目)這些操作過去需要鎖定整個表,因為它們需要兩個方法調用才能完成(例如putIfAbsent()
需要調用containsKey()
和put()
,包含在一個synchronized
塊中,如果你使用的話標准的Map
實現。)再一次,通過避免鎖定整個表,您可以使用這些方法獲得更大的吞吐量。
同步這些操作在這里沒有任何好處 - 如果您不需要同步,它實際上會降低性能。
創建ConcurrentHashMap
的原因是同步映射(在問題中手動實現或者以通常的方式使用Collections.synchronizedMap(map)
實例化)在許多線程訪問時顯示不良性能。 Put和get操作是阻塞的,因此所有其他線程必須等待並且不能同時訪問映射。 ConcurrentHashMap
- 顧名思義 - 允許並發訪問。 如果添加同步,則會失去此優勢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.