[英]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在get
和put
之間不變? 因為從我的理解來看,如果線程在執行get
之后搶占了,同時其他一些線程更新了平衡, put
將使用過時的平衡來執行更新。
Java 8向Map
接口添加了一堆更新方法,並為ConcurrentHashMap
提供了原子性保證。 在您的情況下,您可以執行以下操作:
public void add(int accountId, int amountToAdd){
balances.computeIfPresent(accountId, (key, currentBalance) -> currentBalance + amountToAdd);
}
整個方法調用是原子執行的 。 在進行計算時,可能會阻止其他線程在此映射上進行的某些嘗試的更新操作,因此計算應簡短而簡單,並且不得嘗試更新此映射的任何其他映射。
您可以使用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.