簡體   English   中英

我可以將 ConcurrentHashMap 與 Integer 一起用於線程安全計數器嗎?

[英]Can I use ConcurrentHashMap with Integer for thread safe counters?

我想要幾個櫃台,我可以按名稱尋址。 所以,我可以通過這種方式實現它:

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);

它編碼線程安全嗎?

我認為是的,因為我們因為ConcurrentHashMap進行了同步訪問,並且設置新引用也是線程安全的操作。 由於安全發布,其他線程會看到這種變化,當我們在ConcurrentHashMap保留存儲桶鎖時會發生這種情況。

是的,它是線程安全的,您可以測試:

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadsafeExample {

    public static void main(String[] args) throws Exception {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        int count = 1000;
        AtomicInteger doneTasks = new AtomicInteger();
        Thread[] threads = new Thread[count];
        for(int i = 0 ; i < threads.length ; ++i) {
            threads[i] = new Thread(() -> {
                map.computeIfAbsent("key", k -> new Integer(0));
                map.computeIfPresent("key", (k, v) -> v + 1);
                doneTasks.incrementAndGet();
            });
        }
        for(int i = 0 ; i < threads.length ; ++i)
            threads[i].start();

        while (doneTasks.get() < count)
            Thread.sleep(3);

        System.out.println("we expected count of key is: " + count + ", and we get: " + map.get("key"));
    }

}

輸出:

we expected count of key is: 1000, and we get: 1000

您可以替換:

map.computeIfAbsent("key", k -> new Integer(0));
map.computeIfPresent("key", (k, v) -> v + 1);

經過

map.compute("key", (k, v) -> v == null ? 1 : v + 1);

假設第一條語句, map.computeIfAbsent("key", k -> new Integer(0)); 發生在“初始化時間”,然后有一堆線程執行形式map.computeIfPresent("key", (k, v) -> v + 1); ,是的,算法將是正確的(我是否理解您的意圖?)。

JDK 的最新版本保證對ConcurrentHashMap.computeIfPresent()調用不僅會調用以線程安全方式傳入的表達式,還會保證如果其他線程同時嘗試對相同的鍵進行操作,它們會阻塞並排隊,這樣所有的變化都會按順序發生(這在分布式系統的說法中稱為可串行化)。

暫無
暫無

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

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