Банкомат

  • 9
  • Недоступна
Разберись, как работает программа. Во время тестирования лог содержит следующее: ..... Добавляем 1000, на счету 1000 Тратим 100, на счету 800 Тратим 100, на счету 800 Тратим 100, на счету 800 Тратим 100, на счету 700 ..... Создан баг: деньги не правильно списываются со счета. Твоя задача:
Вы не можете решать эту задачу, т.к. не залогинены.
Комментарии (248)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
6 сентября, 07:21
Я правильно понимаю что до synchronized у нас списание из balance могло происходить еще до того как туда записывалось до конца зачисление? а то дебагером иду и значения с минусом получаются у balance до synchronize
Viacheslav Paninskii
Уровень 29, Russian Federation
4 сентября, 10:14
Обьясните please зачем тут происходит делегирование методов ?
Alexandr
Уровень 19, Нижний Новгород, Russian Federation
4 июля, 17:13
А вот если синхронизировать не сами методы, а конкретный участок кода в методе, например, где упоминаются одинаковые переменные. Это можно считать правильным решением? Или всё же валидатор прав и необходимо синхронизировать всё сразу? Вывод что так, что так одинаковый.
Loony.java
Уровень 28, Uzbekistan
24 сентября, 14:36
Тот же вопрос Если засунуть тело метода в блок синхронайз, то вывод такой же, но валидатор ругается
Айбелив Айкенфлаев
Уровень 36, Москва, Россия
20 июня, 18:53
Когда сделал так, чтобы деньги прибавлялись быстрее чем тратились, в консоль было так приятно смотреть, будто это реальные уведомления банка
Reviksedy
Уровень 35
18 марта, 14:27
два последних требования прямо говорят что делать
Nikolay Veselov
Уровень 48, Stavropol, Russian Federation
16 марта, 15:21
Сначала сделал через синхронизацию на классе BankAccount, валидатор не принял, хотя работа программы корректная. Остался вопрос, в итоге так можно было делать или нет?
NonGrata
Уровень 42, Israel
27 марта, 17:34
Я в методе run() поставил синхронизацию на BankAccount.class и визуально работа даже лучше выглядит чем через решение, любопытно если все таки это объективно корректно или нет,
Anonymous #2856674 Software Developer
27 апреля, 05:07
Если ты на Run поставил синхронизацию на мютекс BankAccount.class , значит ты вообще заблочил одновременное выполнение потоков - ни один из них не может запуститься, пока работает первый Собственно смысл потока вообще исчезает
NonGrata
Уровень 42, Israel
27 апреля, 18:13
Тоже верно, если исходить из логики что карта может одновременно использоваться в разных местах и для разных целей (типа одновременно снятия денег с разных мест + в то же время что бы туда деньги заходили тоже)
Лик Вадим
Уровень 35, Москва, Russian Federation
9 марта, 09:50
Получить верное решение в этой задаче легко, а вот понять почему это решение верно - сложнее. Я в итоге получил два ПОЧЕМУ, в которых пока не разобрался: 1.В задаче есть два метода withdraw с разными входящими параметрами: withdraw(String money) и withdraw(BigDecimal money) при этом работа первого заключается в вызове второго из своего тела с преобразованием входящего параметра money из String в BigDecimal. та же самая картина и с deposit. Я намеренно не синхронизировал все методы withdraw и deposit. А только первые из них, с входящим параметром money типа String. Программа при этом работала корректно. Моя логика была проста: если синхронизирован первый метод, а второй вызывается из его тела, то пока работает первый в режиме синхронизации, никакая сторонняя нить, кроме той что уже заняла мьютекс объекта в первом не сможет работать с ним во втором методе, даже если второй метод не синхронизирован. Иными словами я считал ( и считаю) что синхронизировать только методы withdraw(String money) и deposit(String money) в данном конкретном случае было бы достаточно. И корректно работающий код был этому подтверждением. Валидатор с этим не согласился. Вопрос почему? Это потому что уместен подход - синхронизируй все что изменяет общие данные, так правильно и точка. Или я в самом механизме синхронизации что то не верно понял? 2. Я намеренно не добавил к переменной account слово volatile. Думал валидатор такое решение не примет. Но его он как раз пропустил. Исходя из понимания теоретической части : Если переменной , значение которой могут менять разные потоки не присвоить volatile, то возможны ситуации, когда значения этой переменной могут храниться в не общедоступной кеш памяти, а потому изменения, вносимые одной из нитей в значение этой переменной - другии нити могут не увидеть. Что бы избежать этого - нужно объявить эту переменную volotile.В моем понимании переменная account как раз подпадает под этот случай, но валидатор считает иначе. Почему?
SWK
Уровень 26
6 апреля, 11:01
1. Это работает. Но это очевидно избыточно. Поскольку методы со строками сами ничего не делают, кроме преобразования параметров, они не могут что-то нарушить. А могут нарушить основные. Их и надо синхронизировать. 2. Тоже не понимаю.
Andrey
Уровень 41, Санкт-Петербург, Россия
23 апреля, 13:15
1. Соглашусь с @SWK 2. volatile замедляет программу. А если у нас все методы, которые могут повлиять на состояние аккаунта - synchronized, то и необходимость в volatile отпадает (накидайте плюсов для ачивки пожалуйста 🙃)
Maksim Java Developer
7 декабря 2021, 11:23
Отличная задача в которой повторяем огромные числа BigDecimal, делегирование в методах и паттерн producer-consumer. Очень понравилось!
Sergey Kornilov
Уровень 39, Petropavlovsk, Казахстан
6 ноября 2021, 10:52
Всего эту задачу решили 23088 учеников.
Игорь Евгеньевич
Уровень 41, Хабаровск, Россия
14 октября 2021, 10:57
public synchronized void deposit(String money) { deposit(new BigDecimal(money)); } public synchronized void withdraw(String money) throws NotEnoughMoneyException { withdraw(new BigDecimal(money)); } В этих двух последних методах класса BankAccount в качестве аргумента передаётся строка. Далее они вызывают такой же метод принимающий BigDecimal и передают в него new BigDecimal с этой строкой. Вопрос! Как это работает?
Anonymous #2583212
Уровень 40
21 октября 2021, 10:44
Это рекурсия. Почитайте об этом
Dmitry Noskov
Уровень 50, Москва, Russian Federation
24 октября 2021, 17:00
это не рекурсия, это перегрузка методов:
public void deposit(BigDecimal money) {};
public void deposit(String money) {};
с точки зрения JVM это два разных независимых друг от друга метода. рекурсия была бы, если бы метод в своём теле вызывал себя.
Anonymous #2583212
Уровень 40
25 октября 2021, 04:00
Вы правы, я ошибся.