У меня есть Bank
класс со списком Account
.В банке есть метод transfer()
для перевода значения с одного счета на другой.Идея состоит в том, чтобы заблокировать учетные записи from
и to
в рамках перевода.
Для решения этой проблемы у меня есть следующий код (имейте в виду, что это очень тривиальный пример, потому что это простоПример:
public class Account {
private int mBalance;
public Account() {
mBalance = 0;
}
public void withdraw(int value) {
mBalance -= value;
}
public void deposit(int value) {
mBalance += value;
}
}
public class Bank {
private List<Account> mAccounts;
private int mSlots;
public Bank(int slots) {
mAccounts = new ArrayList<Account>(Collections.nCopies(slots, new Account()));
mSlots = slots;
}
public void transfer(int fromId, int toId, int value) {
synchronized(mAccounts.get(fromId, toId)) {
synchronized(mAccounts.get(toId)) {
mAccounts.get(fromId).withdraw(value);
mAccounts.get(toId).deposit(value);
}
}
}
}
Это работает, но не предотвращает взаимоблокировки .Чтобы это исправить, нам нужно изменить синхронизацию следующим образом:
synchronized(mAccounts.get(Math.min(fromId, toId))) {
synchronized(mAccounts.get(Math.max(fromId, toId))) {
mAccounts.get(fromId).withdraw(value);
mAccounts.get(toId).deposit(value);
}
}
Но компилятор предупреждает меня о вложенных блоках синхронизации , и я верю, что это плохо?Кроме того, я не очень люблю решение max / min (я не был тем, кто придумал эту идею), и я хотел бы избежать этого, если это возможно.
Как можно решить эти 2 проблемывыше?Если бы мы могли заблокировать более одного объекта, мы бы заблокировали и учетную запись from
и to
, но мы не можем этого сделать (насколько я знаю).Каково решение тогда?