假设有以下 Account 类的两个对象 - account1 和 account2。并且有两个线程T1和T2。
T1 正在将金额 100 从账户 1 转移到账户 2,如下所示:
account1.transfer(account2, 100);
同样,T2 将金额 50 从 account2 转移到 account1:
account2.transfer(account1, 50);
Transfer() 方法显然容易出现死锁,因为两个线程 T1 和 T2 会尝试以相反的顺序获取锁。 (线程 T1 将首先尝试获取 account1 上的锁,然后再获取 account2 上的锁。而线程 T2 将尝试获取 account2 上的锁,然后再获取 account1 上的锁。)
(在这种情况下)确保始终保证锁定顺序的最佳方法是什么?
public class Account {
private float balance;
public class Account() {
balance = 5000f;
}
private void credit(float amt) {
balance += amt;
}
// To exclude noise assume the balance will never be negative
private void debit(float amt) {
balance -= amt;
}
// Deadlock prone as the locking order is not guaranteed
public void transfer(Account acc2, float amt) {
synchronized(this) {
synchronized(acc2) {
acc2.debit(amt);
this.credit(amt);
}
}
}
}
我只允许一个线程访问“帐户”数据。任何其他想要转移资金的线程都必须将一个“transferRequest”对象排队到其中,该对象包含帐户 ID、要转移的金额、异常/错误消息字段和回调/事件,并以 TransferRequest 作为线程的参数当它尝试事务时调用。
然后,传输将被完整序列化,唯一的锁位于队列中,因此不可能出现死锁。
我讨厌多把锁,无论顺序是否正确。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)