Как перевести деньги с одного счета на другой атом? Для:
public class Account {
public Account(BigDecimal initialAmount) {...}
public BigDecimal getAmount() {...}
public void setAmount(BigDecimal amount) {...}
}
Я ожидаю, что псевдокод:
public boolean transfer(Account from, Account to, BigDecimal amount) {
BigDecimal fromValue = from.getAmount();
if (amount.compareTo(fromValue) < 0)
return false;
BigDecimal toValue = to.getAmount();
from.setAmount(fromValue.add(amount.negate()));
to.setAmount(toValue.add(amount));
return true;
}
безопасно обновлять учетные записи в многопотоковой среде, я вижу случай с опасностью как:
acc1 --> acc2 || acc2 --> acc1
acc1 --> acc2 || acc2 --> acc3 || acc3 --> acc1
...
Самое простое решение - сделать блокировку для общего объекта, но это будет неэффективно для таких случаев, как:
acc1 --> acc2 || acc3 --> acc4 and acc1 != acc3 and acc2 != acc4
Я ожидаю, что независимые ходы выполняются параллельно, зависимые в последовательности.
UPDATE Кажется, что предлагаемое решение:
synchronize (acc1) {
synchronize (acc2) {
....
}
}
приводит к тупиковой ситуации, когда 2 замка приобретаются последовательно...
ОБНОВЛЕНИЕ 2 Что вы подразумеваете под "безопасным обновлением учетных записей в многопотоковой среде"? Единственное беспокойство в том, что счета не будут иметь минус средства или есть какая-то другая проблема?
Если acc1(2); acc2(3)
и acc1 --1--> acc2
и acc2 --2--> acc1
я ожидаю согласованности: (acc1, acc2)
имеет значение (3, 2)
, а не (4, 2)
или (3, 4)
, если вы получаете промежуточное значение учетной записи во время одновременного выполнения.
сколько параллельных транзакций вы ожидаете за раз? 1000-10000 - поэтому блокировка общего объекта неэффективна.