Разберись, как работает программа.
Во время тестирования лог содержит следующее:
.....
Добавляем 1000, на счету 1000
Тратим 100, на счету 800
Тратим 100, на счету 800
Тратим 100, на счету 800
Тратим 100, на счету 700
.....
Создан баг: деньги не правильно списываются со счета.
Твоя задача:
Банкомат
- 9
Недоступна
Комментарии (243)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Айбелив Айкенфлаев
20 июня, 18:53
Когда сделал так, чтобы деньги прибавлялись быстрее чем тратились, в консоль было так приятно смотреть, будто это реальные уведомления банка
0
Reviksedy
18 марта, 14:27
два последних требования прямо говорят что делать
+3
Nikolay Veselov
16 марта, 15:21
Сначала сделал через синхронизацию на классе BankAccount, валидатор не принял, хотя работа программы корректная. Остался вопрос, в итоге так можно было делать или нет?
+1
NonGrata
27 марта, 17:34
Я в методе run() поставил синхронизацию на BankAccount.class и визуально работа даже лучше выглядит чем через решение, любопытно если все таки это объективно корректно или нет,
0
Anonymous #2856674 Software Developer
27 апреля, 05:07
Если ты на Run поставил синхронизацию на мютекс BankAccount.class , значит ты вообще заблочил одновременное выполнение потоков - ни один из них не может запуститься, пока работает первый
Собственно смысл потока вообще исчезает
+2
NonGrata
27 апреля, 18:13
Тоже верно, если исходить из логики что карта может одновременно использоваться в разных местах и для разных целей (типа одновременно снятия денег с разных мест + в то же время что бы туда деньги заходили тоже)
0
Лик Вадим
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 как раз подпадает под этот случай, но валидатор считает иначе. Почему?
+2
SWK
6 апреля, 11:01
1. Это работает. Но это очевидно избыточно. Поскольку методы со строками сами ничего не делают, кроме преобразования параметров, они не могут что-то нарушить. А могут нарушить основные. Их и надо синхронизировать.
2. Тоже не понимаю.
0
Andrey
23 апреля, 13:15
1. Соглашусь с @SWK
2. volatile замедляет программу. А если у нас все методы, которые могут повлиять на состояние аккаунта - synchronized, то и необходимость в volatile отпадает
(накидайте плюсов для ачивки пожалуйста 🙃)
+5
Максим Белоусов
7 декабря 2021, 11:23
Отличная задача в которой повторяем огромные числа BigDecimal, делегирование в методах и паттерн producer-consumer.
Очень понравилось!
0
Sergey Kornilov
6 ноября 2021, 10:52
Всего эту задачу решили 23088 учеников.
0
Игорь Евгеньевич
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 с этой строкой. Вопрос! Как это работает?
0
Anonymous #2583212
21 октября 2021, 10:44
Это рекурсия. Почитайте об этом
0
Dmitry Noskov
24 октября 2021, 17:00
это не рекурсия, это перегрузка методов:
с точки зрения JVM это два разных независимых друг от друга метода. рекурсия была бы, если бы метод в своём теле вызывал себя. +7
Anonymous #2583212
25 октября 2021, 04:00
Вы правы, я ошибся.
0
Денис Измайлов Инженер- программист в CloudFactory
2 сентября 2021, 07:52
И снова , условие:
"Создан баг:
деньги не правильно списываются со счета.
Твоя задача:
найти и исправить ошибку"
так почему синхронизация по объекту в тредах НЕ решение, а синхронизация методов решение ?
ОБА решения удовлетворяют поставленной задаче.
Да. В реквайрементах описано про методы. НО ЭТО НЕ УСЛОВИЕ ЗАДАЧИ!!! ё-маё.
ОТКУДА "реквайремнеты" вытекают из условия ?!
0
SWK
6 апреля, 11:13
Дык, синхронизация _чего_ "по объекту в тредах"? Вызова тех же методов?
Один фиг, ключевое место - методы.
0
Torba Z Dimom
6 августа 2021, 22:17
Как и в многих предыдущих задачах самое сложное("долгое") - понять что делает програма. и чем дальше тем больше строк.... хорошая тренировка, но вот времени жрет вагон.
0
Андрей Dungeon Master
9 ноября 2021, 09:41
вагон? пфф, ищешь метод, который отвечает на съем и взнос денег и синхронизируешь, 20 секунд решал задачу
0
Саня
29 июня 2021, 10:43
Вот специально не стал перед отправкой синхронизировать deposit() -- и валидатор конечно же ругнулся -- а по факту всё работает правильно. Ну и зачем тогда этот метод синхронизовывать??
+8
Галина
21 сентября 2021, 10:25
Я тоже не очень поняла зачем его синхронизировать, если там отдельная нить создается для вызова deposit().
0
Галина
21 сентября 2021, 10:26
Вроде как надо синхронизировать всё, что использует общие ресурсы. Но если для этого одна нить, то зачем ее синхронить?
0
NonGrata
27 марта, 17:37
Да, я тоже не понял, в чем проблема если деньги будут заходить на счет, в то же время пока их тратят? Тогда бы не пришлось видеть надпись недостаточно средств...
0
SWK
6 апреля, 11:11
В том, что одна сумма пропадёт:
1 читает размер счёта.
2 читает размер
1 считает, сколько должно получиться после операции.
2 считает, сколько должно получиться после операции.
1. записывает результат.
2. записывает результат.
Сумма, которую вносила/снимала 1я нить, пропала.
0