Войти Регистрация
Конкурентность

2. Перевод между счетами: две блокировки

Средняя

Java · 32 строк

transfer вызывают 64 потока обработки платежей. Клиенты часто переводят деньги друг другу в обе стороны: между своими счетами, мужу и обратно.

Отметьте строки с ошибками.

В работе: Ядро переводов между счетами внутри банка.

Как проверяем Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Плюс 1 вопрос про поведение программы — на зачёт не влияют. Ответ один на подход: после него показываем разбор.
synchronizedдедлокпорядок захватаcheck-then-act

Источник: Т‑Банк: секция Java, многопоточность — исправить код. Условие пересказано своими словами.

Давали на собеседовании? Ответов пока мало — ваш поможет.
  1. import java.math.BigDecimal;
  2. public class TransferService {
  3. static class Account {
  4. final long id;
  5. BigDecimal balance;
  6. Account(long id, BigDecimal balance) {
  7. this.id = id;
  8. this.balance = balance;
  9. }
  10. }
  11. // Вызывается из пула обработчиков платежей.
  12. public void transfer(Account from, Account to, BigDecimal amount) {
  13. if (from.balance.compareTo(amount) < 0) {
  14. throw new IllegalStateException("Недостаточно средств на счёте " + from.id);
  15. }
  16. synchronized (from) {
  17. synchronized (to) {
  18. from.balance = from.balance.subtract(amount);
  19. to.balance = to.balance.add(amount);
  20. }
  21. }
  22. }
  23. // Сумма по двум счетам для виджета «Все деньги».
  24. public BigDecimal total(Account a, Account b) {
  25. return a.balance.add(b.balance);
  26. }
  27. }