gpt4 book ai didi

java - 如何在 ConcurrentHashMap 线程安全中更新 BigDecimal

转载 作者:太空狗 更新时间:2023-10-29 22:45:22 26 4
gpt4 key购买 nike

我正在制作一个应用程序,它需要一堆日记条目并计算总和。

当有多个线程调用addToSum() 方法时,下面的方法是线程/并发安全的。我想确保每次调用都能正确更新总数。

如果不安全,请说明我必须做什么来确保线程安全。

我需要同步 get/put 还是有更好的方法?

private ConcurrentHashMap<String, BigDecimal> sumByAccount;

public void addToSum(String account, BigDecimal amount){
BigDecimal newSum = sumByAccount.get(account).add(amount);
sumByAccount.put(account, newSum);
}

非常感谢!

更新:

谢谢大家的回答,我已经知道上面的代码不是线程安全的

感谢 Vint 建议使用 AtomicReference 作为 synchronize 的替代方案。我以前使用 AtomicInteger 来保存整数和,我想知道 BigDecimal 是否有类似的东西。

两者的优劣是否有定论?

最佳答案

您可以像其他人建议的那样使用同步,但如果想要一个最小阻塞的解决方案,您可以尝试将 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) 。现在,在您调用 newSum.get() 的 for 循环之后的任何时候,它都会有已添加到的 BigDecimal 对象。

您想在此处使用循环,因为有可能两个线程正在尝试添加到同一个 AtomicReference。可能会发生一个线程成功而另一个线程失败的情况,如果发生这种情况,只需使用新的附加值重试。

在中等线程争用情况下,这会是一个更快的实现,在高争用情况下,您最好使用 synchronized

关于java - 如何在 ConcurrentHashMap 线程安全中更新 BigDecimal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8567596/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com