簡體   English   中英

是否需要將ConcurrentHashMap包裝在同步塊中?

[英]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的好處。 您也可以使用帶有synchronizedsynchronizedMap()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.

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