假设有以下帐户类的两个对象 - account1和account2。有两个线程T1和T2。如何确保锁定顺序以避免死锁?
T1从帐户1转移量100到帐户2如下:
account1.transfer(account2, 100);
类似地,T2从帐户2转移量为50〜帐户1:
account2.transfer(account1, 50);
转印()方法显然是容易因为两个线程T1和T2试图以相反的顺序获取锁定而导致死锁。 (线程T1会先尝试获取帐户1上的锁定,然后是帐户2,而线程T2将尝试获取帐户2和帐户1上的锁定。)
确保锁定顺序为最佳方式(在此情况下)总是保证?
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);
}
}
}
}
这是一个解决方案 - 谢谢。但是,如果有4个帐户a1到a4和4个线程T1到T4。 T1和T2与a1和a2一起工作。 T3和T4与a3和a4一起工作。我希望(T1和T2组)和(T3和T4组)同时工作,即这两组操作不需要等待锁定。 – Learner
@Learner,这绝对不是问题,你只需要为每个帐号对组合定义一个互斥对象。在4个帐户的情况下,您可以在矢量中使用6个单独的互斥锁。 –
因此,实现变得相当复杂,以推广互斥的排列和组合。另外,如果有100万个帐户,我无法想象需要多少个互斥体?!我们可能会对互斥量进行惰性初始化,但这会引入一组新的复杂性。 – Learner