Вы можете использовать синхронизированный, как предложили другие, но если хотите минимально блокирующее решение, вы можете попробовать AtomicReference
в качестве хранилища для 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;
}
}
Изменить - я объясню это больше:
AtomicReference использует CAS , чтобы атомарно назначить одну ссылку. Цикл говорит это.
Если текущее поле, хранящееся в AtomicReference == oldVal
[их расположение в памяти, а не их значение], замените значение поля, хранящегося в AtomicReference, на oldVal.add(amount)
. Теперь, каждый раз, когда после цикла for вы вызываете newSum.get (), он будет иметь объект BigDecimal, который был добавлен в.
Здесь вы хотите использовать цикл, поскольку возможно, что два потока пытаются добавить к одному и тому же AtomicReference. Может случиться так, что один поток завершится успешно, а другой завершится неудачей, если это произойдет, просто попробуйте еще раз с новым добавленным значением.
При умеренном конфликте потоков это будет более быстрой реализацией, а при высоком конфликте лучше использовать synchronized