From 73427cd81f33f3ad648d91290b8bf887390dd53f Mon Sep 17 00:00:00 2001 From: Matin-Ardestani Date: Thu, 25 Jun 2026 00:06:34 +0330 Subject: [PATCH 1/2] Implement Answers.md --- .idea/.gitignore | 10 +++++++++ .idea/compiler.xml | 13 +++++++++++ .idea/encodings.xml | 7 ++++++ .idea/jarRepositories.xml | 20 +++++++++++++++++ .idea/misc.xml | 12 ++++++++++ .idea/vcs.xml | 6 +++++ Answers.md | 47 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 115 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 Answers.md diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..812c3f9 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..f4fe6ed --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..eba6e1f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Answers.md b/Answers.md new file mode 100644 index 0000000..1546cbb --- /dev/null +++ b/Answers.md @@ -0,0 +1,47 @@ +## Question 1 +An atomic variable in Computer Science refers to a basic data or input variable that is used to build performance variables. These variables are not summaries or ratios, but rather fundamental building blocks in operational systems. + +Atomic variables allow multiple threads to safely read and update a shared value without using explicit locks, guaranteeing that operations like increment-and-update happen as a single, uninterruptible step. Ordinary variables don't provide this guarantee—if multiple threads modify them concurrently, updates can be lost due to race conditions. + +## Question 2 +`AtomicInteger` + +`AtomicLong` + +`AtomicBoolean` + +`AtomicReference` for any type of object. + +## Question 3 +| | Locks (`synchronized`/`ReentrantLock`) | Atomic Variables | +|---|---|---| +| Mechanism | Blocking (mutual exclusion) | Lock-free | +| Scope | Can protect multiple statements/variables | Single variable only | +| Performance | Slower under contention | Generally faster | +| Deadlock risk | Possible | None | +| Best for | Complex critical sections | Simple counters, flags, single values | + +## Question 4 +A program can be completely free of race conditions yet still perform poorly, because the very mechanisms used to guarantee correctness — such as locks or CAS — introduce overhead. When many threads compete for the same shared resource, they end up **blocking or repeatedly retrying**, which sharply reduces throughput even though correctness is fully preserved. + +Some concurrency-related factors that may limit scalability even when correctness iss guaranteed: + +1. Lock contention +2. Context switching overhead +3. Cache coherence traffic + +## Question 5 +Despite the three factors given in the previous question there is a vital factor which is **limited CPU cores**. + +once threads exceed available cores, they compete for the same processing units, adding scheduling overhead instead of true parallelism. + +Context-switching overhead – the OS spends more time switching between threads than executing actual work. + +Cache coherence traffic – shared/false-shared memory locations cause costly cross-core cache invalidation. + +## Question 6 +A precise timing where two or more threads each acquire one lock and then attempt to acquire the other's lock simultaneously. + +1. Stress testing with high concurrency – run many more threads than in normal testing. +2. Deliberate interleaving control / thread scheduling tools – use tools or techniques that artificially manipulate thread timing to force specific interleavings, such as: + Inserting `Thread.sleep()` or `yield()` calls strategically between lock acquisitions. \ No newline at end of file -- 2.54.0 From 6051f30a983c5edaf6823e6936f48eb1f1d557b3 Mon Sep 17 00:00:00 2001 From: Matin-Ardestani Date: Thu, 25 Jun 2026 00:36:21 +0330 Subject: [PATCH 2/2] 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 -- 2.54.0