gpt4 book ai didi

java - Java中的多线程: how to transfer funds between accounts correctly?

转载 作者:行者123 更新时间:2023-12-01 17:20:28 25 4
gpt4 key购买 nike

尝试在多线程环境中在条件账户之间进行转账,我的方法有多真实以及我错在哪里?

按照计划,我在 main 中创建一个新线程,在这个新线程中初始化一个 Transfer 类型的新类,在我从数据库中获取 2 个帐户的数据后,我随机确定我想要的金额随机转移。我将更改翻译并写回数据库。账户中所有资金的总和必须保持正确。也就是说,如果我们有 50 个账户,每个账户有 1000 block 钱(总共 50,000 block ),那么所有交易之后应该不会多,也不会超过 50,000。

如果线程不超过 5-10 个且线程 hibernate 时间超过 500 毫秒,则下面描述的方法有效。也许我解决问题的方法是错误的。我尝试使用tryLock,结果是一样的。总的来说,钱会变成正数,然后变成负数。

另外,我正在尝试在 Hibernate 上执行此操作。
我有什么:
1.对某个银行账户进行类-Account(@Entity)
2. TransferThread类扩展Thread
3. 类(class)转学 - 转学工作 4.主类

现在看起来像这样:类帐户(设置/获取(我没有在这里写它们,但它们在那里)):

public class Account {
private int id;
private int money;

public Account() {
}
public void widrawal(int sum) {
money += sum;
}
public void send(int sum) {
money -= sum;
}
}

类TransferThread(根据想法,完成事务并 hibernate 随机时间(10次)):

public class TransferThread extends Thread {
Transfer transfer= new Transfer();
AtomicInteger atomicInteger = new AtomicInteger();

public void run() {
atomicInteger.set(10);
while (atomicInteger.get() > 0) {
//thread sleep for random time
int a = (int) (Math.random() * (500 - 100)) + 100;
try {
transfer.transaction();
atomicInteger.getAndDecrement();
Thread.sleep(a);
} catch (InterruptedException e) {
}
}
}
}

类(class)转学:

public class Transfer {




public void transaction() throws InterruptedException {


int sumSpis = (int) (Math.random() * 100) + 10;
int ranAccount1 = (int) (Math.random() * 50) + 1;
int ranAccount2 = (int) (Math.random() * 50) + 1;
Account a1 = null;
Account a2 = null;
a1 = HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Account.class, ranAccount1);
a2 = HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Account.class, ranAccount2);

int fromId = a1.getId();
int toId = a2.getId();

if (fromId < toId) {
synchronized (a1) {
synchronized (a2) {
transfer(a1, a2, sumSpis);

}
}
} else {
synchronized (a2) {
synchronized (a1) {
transfer(a1, a2, sumSpis);
}
}
}

System.out.println("amount: " + sumSpis);


}

public void transfer(Account account1, Account account2, int sum) {
if (account1.getId() == account2.getId()) {
System.out.println("same IDs");
return;
}

if (account1.getMoney() < sum) {
System.out.println("not enough account funds");
return;
}

account1.widrawal(sum);
account2.send(sum);

Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.update(account1);
session.update(account2);
tx.commit();
session.close();
}
}

最佳答案

操作顺序应如下:获取 session 、启动数据库事务、从数据库获取 acc1 的数据、从数据库获取 acc2 的数据、转账、将 acc1 的数据保存到数据库、将 acc2 的数据保存到数据库、提交数据库事务。

在代码中,您从数据库获取帐户数据并将新数据保存在单独的 session 中,这意味着事务也是单独的。并且有可能在从数据库获取和保存到数据库之间,我的一个线程另一个线程已经更新了这些帐户的数据,并且您正在用过时的数据覆盖该数据。

关于java - Java中的多线程: how to transfer funds between accounts correctly?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61302164/

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