gpt4 book ai didi

Java同步: atomically moving money across account pairs?

转载 作者:IT老高 更新时间:2023-10-28 20:40:58 25 4
gpt4 key购买 nike

如何从一个帐户向另一个 atomic 进行汇款?类:

public class Account {
public Account(BigDecimal initialAmount) {...}
public BigDecimal getAmount() {...}
public void setAmount(BigDecimal amount) {...}
}

我期望以下伪代码:

public boolean transfer(Account from, Account to, BigDecimal amount) {
BigDecimal fromValue = from.getAmount();
if (amount.compareTo(fromValue) < 0)
return false;
BigDecimal toValue = to.getAmount();
from.setAmount(fromValue.add(amount.negate()));
to.setAmount(toValue.add(amount));
return true;
}

在单线程(或顺序)环境中安全地更新帐户。

如果是多线程/并发环境,我会看到危险情况:

acc1 --> acc2  ||  acc2 --> acc1
acc1 --> acc2 || acc2 --> acc3 || acc3 --> acc1
...

最简单的解决方案是阻止共享对象,但对于以下情况会效率低下:

acc1 --> acc2  ||  acc3 --> acc4  and  acc1 != acc3 and acc2 != acc4

我希望独立传输是并行执行的。

更新似乎建议的解决方案:

synchronize (acc1) {
synchronize (acc2) {
....
}
}

由于顺序获取 2 个锁而导致死锁...

更新 2 “在多线程环境中安全更新帐户”到底是什么意思?唯一担心的是账户最终不会有负资金还是有其他问题?

如果 acc1(2); acc2(3)acc1 --1--> acc2acc2 --2--> acc1 我期望一致性:(acc1, acc2)(3, 2) 值,但没有 (4, 2)(3, 4)。总数应该是 5,而不是 1+3=4 或 4+3=7。

您希望一次有多少并发事务? 1000-10000 - 所以锁定共享对象效率不高。

最佳答案

一个简单的解决方案是为每个帐户使用一个锁,但为了避免死锁,您必须始终以相同的顺序获取锁。所以,你可以有一个最终的账号ID,然后先获取ID较小的账号的锁:

public void transfer(Account acc1, Account acc2, BigDecimal value) {
Object lock1 = acc1.ID < acc2.ID ? acc1.LOCK : acc2.LOCK;
Object lock2 = acc1.ID < acc2.ID ? acc2.LOCK : acc1.LOCK;
synchronized (lock1) {
synchronized (lock2) {
acc1.widrawal(value);
acc2.send(value);
}
}
}

关于Java同步: atomically moving money across account pairs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29280857/

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