Suppose, I have concurrentHashMap code such as below:
ConcurrentHashMap<Integer,Integer> balances = new ConcurrentHashMap<>();
public void add(int accountId, int amountToAdd){
int currentBalance = balances.get(accountId);
balances.put(accountId, currentBalance + amountToAdd);
}
This add
method is called from multiple threads, there can be attempt to update the amount of the same accountId at same time.
How to ensure the currentBalance doesn't change between the get
and the put
? Because from my understanding, if thread preempts after doing get
, and meanwhile some other thread updates the balance, put
will perform update with stale balance.
Java 8 adds a bunch of update methods to the Map
interface, with atomicity guarantees for ConcurrentHashMap
. In your case, you could do something like this:
public void add(int accountId, int amountToAdd){
balances.computeIfPresent(accountId, (key, currentBalance) -> currentBalance + amountToAdd);
}
The entire method invocation is performed atomically . Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map.
You can use a hashmap of AtomicIntegers:
ConcurrentHashMap<Integer,AtomicInteger> balances = new ConcurrentHashMap<>();
AtomicInteger implements the compare and swap operation.
And then:
public void add(int accountId, int amountToAdd){
balances.get(accountId).addAndGet( amountToAdd );
}
to create a new accont - and don't overwrite an account already created and initialised with some amount by the other thread - use this:
public void addNewAccount(int accountId){
balances.putIfAbsent( accountId, new AtomicInteger(0) );
}
you can also combine both metods and use only one:
public void add(int accountId, int amountToAdd){
balances.putIfAbsent( accountId, new AtomicInteger(0) );
balances.get(accountId).addAndGet( amountToAdd );
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.