У меня есть класс Bank
со списком Account
. В банке есть метод transfer ()
для перевода стоимости с одного счета на другой. Идея состоит в том, чтобы заблокировать учетные записи из
и в
во время передачи.
Для решения этой проблемы у меня есть следующий код (имейте в виду, что это очень тривиальный пример, потому что это всего лишь пример):
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 проблемы, указанные выше? Если бы мы могли заблокировать более одного объекта, мы бы заблокировали как из
, так и в
учетную запись, но мы не можем этого сделать (насколько мне известно). Какое же тогда решение?