From 6051f30a983c5edaf6823e6936f48eb1f1d557b3 Mon Sep 17 00:00:00 2001 From: Matin-Ardestani Date: Thu, 25 Jun 2026 00:36:21 +0330 Subject: [PATCH] Implement BankAccount class --- .../java/dev/banking/model/BankAccount.java | 57 +++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/banking/model/BankAccount.java b/src/main/java/dev/banking/model/BankAccount.java index 745ede2..a179dc3 100644 --- a/src/main/java/dev/banking/model/BankAccount.java +++ b/src/main/java/dev/banking/model/BankAccount.java @@ -1,10 +1,16 @@ package dev.banking.model; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + public class BankAccount { private final int accountId; private long balance; + private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + /* * Students may introduce additional fields * such as: @@ -32,7 +38,12 @@ public class BankAccount { * - Should not block unnecessarily if using read/write locks */ public long getBalance() { - throw new UnsupportedOperationException("TODO: implement thread-safe balance read"); + lock.readLock().lock(); + try { + return balance; + } finally { + lock.readLock().unlock(); + } } /* @@ -43,7 +54,15 @@ public class BankAccount { * - Must not lose updates under concurrency */ public void deposit(long amount) { - throw new UnsupportedOperationException("TODO: implement thread-safe deposit"); + if(amount < 0) + throw new IllegalArgumentException("Amount can't be negative!"); + + lock.writeLock().lock(); + try { + balance += amount; + } finally { + lock.writeLock().unlock(); + } } /* @@ -56,7 +75,15 @@ public class BankAccount { * to extend the system (optional) */ public void withdraw(long amount) { - throw new UnsupportedOperationException("TODO: implement thread-safe withdraw"); + if(amount < 0) + throw new IllegalArgumentException("Amount can't be negative!"); + + lock.writeLock().lock(); + try { + balance -= amount; + } finally { + lock.writeLock().unlock(); + } } /* @@ -73,6 +100,28 @@ public class BankAccount { * - Or tryLock with retry strategy */ public void transfer(BankAccount target, long amount) { - throw new UnsupportedOperationException("TODO: implement atomic deadlock-free transfer"); + if (amount < 0) { + throw new IllegalArgumentException("Transfer amount cannot be negative"); + } + if (this == target) { + throw new IllegalArgumentException("Cannot transfer to the same account"); + } + + // we order them by their id so that we always lock the first one to prevent deadLocks taking place. + BankAccount first = this.accountId < target.accountId ? this : target; + BankAccount second = this.accountId < target.accountId ? target : first; + + first.lock.writeLock().lock(); + try { + second.lock.writeLock().lock(); + try { + this.balance -= amount; + target.balance += amount; + } finally { + second.lock.writeLock().unlock(); + } + } finally { + first.lock.writeLock().unlock(); + } } } \ No newline at end of file