簡體   English   中英

在ConcurrentHashMap中,如何同步更新?

[英]In ConcurrentHashMap, how to synchronize update?

假設我有並發HashMap代碼,如下所示:

ConcurrentHashMap<Integer,Integer> balances = new ConcurrentHashMap<>();

public void add(int accountId, int amountToAdd){
     int currentBalance = balances.get(accountId);
     balances.put(accountId, currentBalance + amountToAdd);
}

從多個線程調用此add方法,可以嘗試同時更新同一accountId的數量。

如何確保currentBalance在getput之間不變? 因為從我的理解來看,如果線程在執行get之后搶占了,同時其他一些線程更新了平衡, put將使用過時的平衡來執行更新。

Java 8向Map接口添加了一堆更新方法,並為ConcurrentHashMap提供了原子性保證。 在您的情況下,您可以執行以下操作:

public void add(int accountId, int amountToAdd){
    balances.computeIfPresent(accountId, (key, currentBalance) -> currentBalance + amountToAdd);
}

Java文檔

整個方法調用是原子執行的 在進行計算時,可能會阻止其他線程在此映射上進行的某些嘗試的更新操作,因此計算應簡短而簡單,並且不得嘗試更新此映射的任何其他映射。

您可以使用AtomicIntegers的哈希圖:

ConcurrentHashMap<Integer,AtomicInteger> balances = new ConcurrentHashMap<>();

AtomicInteger實現比較和交換操作。


接着:

public void add(int accountId, int amountToAdd){
     balances.get(accountId).addAndGet( amountToAdd );
}

創建一個新的帳戶-不要覆蓋另一個線程已經創建並初始化了一定金額的帳戶-請使用以下命令:

public void addNewAccount(int accountId){
     balances.putIfAbsent( accountId, new AtomicInteger(0) );
}

您還可以結合使用兩種方法,並且僅使用一種方法:

public void add(int accountId, int amountToAdd){
     balances.putIfAbsent( accountId, new AtomicInteger(0) );
     balances.get(accountId).addAndGet( amountToAdd );
}

暫無
暫無

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

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