You can use synchronized like the others suggested but if want a minimally blocking solution you can try AtomicReference
as a store for the BigDecimal
ConcurrentHashMap<String,AtomicReference<BigDecimal>> map;
public void addToSum(String account, BigDecimal amount) {
AtomicReference<BigDecimal> newSum = map.get(account);
for (;;) {
BigDecimal oldVal = newSum.get();
if (newSum.compareAndSet(oldVal, oldVal.add(amount)))
return;
}
}
Edit - I'll explain this more:
An AtomicReference uses CAS to atomically assigns a single reference. The loop says this.
If the current field stored in AtomicReference == oldVal
[their location in memory, not their value] then replace the value of the field stored in AtomicReference with oldVal.add(amount)
. Now, any time after the for-loop you invoke newSum.get() it will have the BigDecimal object that has been added to.
You want to use a loop here because it is possible two threads are trying to add to the same AtomicReference. It can happen that one thread succeeds and another thread fails, if that happens just try again with the new added value.
With moderate thread contention this would be a faster implementation, with high contention you are better off using synchronized
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…