简体   繁体   中英

In ConcurrentHashMap, how to synchronize update?

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);
}

Javadoc

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM