From 2efd5e3e350bd98b7e464b2247b2f0f18897f705 Mon Sep 17 00:00:00 2001 From: Farnam Jahangard Date: Wed, 10 Jun 2026 17:33:46 +0330 Subject: [PATCH 1/2] answered theoretical questions finished the bonus task in theoretical questions part --- ANSWERS.md | 54 +++++++++++++++++++++++++ src/main/java/bonus/AtomicVsNormal.java | 42 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 ANSWERS.md create mode 100644 src/main/java/bonus/AtomicVsNormal.java diff --git a/ANSWERS.md b/ANSWERS.md new file mode 100644 index 0000000..97301d5 --- /dev/null +++ b/ANSWERS.md @@ -0,0 +1,54 @@ +# Answers + +## Q1 +Atomic variable is a type of variable that combines all three process of: read, write and update into a single operation. +as an example when we write `i++` it may seem like a single operation +but the compiler needs to read `i`(read), add 1 to it (update) and change `i` to new value (write) +since all these operations are combined into one operation race conditions doesn't occur +unlike normal variables. + +## Q2 +`AtomicInteeger`, `AtomicBoolean`.`AtomicLong` & `AtomicReference` + +#### `AtomicInteeger` Use case +used as counters that are shared across threads +#### `AtomicBoolean` Use case +used as flags that are used across threads (like `running` flag) +#### `AtomicLong` Use case +in general anything that needs long operations for multiple threads such as a bank account balance or an id counter +#### `AtomicReference` Use case +it's used whenever you need atomic operations on any object + +## Q3 +locks are used to lock a full block of code, this prevents race conditions as a thread locks the section it's working on when it reaches it + +therefore we should use locks when we wan't to prevent race conditions for a block of code +and use atomic variables on more basic things +## Q4 +this situation may occur because if there are too many threads trying to access a shared resource performance drops because workers sleep more than they do work + +#### Usage of locks +locks make a block of code completely unaccessible for every thread except one +this would cause those other threads to sleep meaning even if you have 100 threads only one of them can work at a time. + +#### Usage of atomic variables +when we use atomic variables and atomic operations, at a curtain point many threads my try to change one variable +only one can successfully access the variable, meaning the rest would fail +this failure is just waste of cpu power. + +## Q5 +majority of mainstream cpus has something around 8 to 16 cores right now +this means one thing +logically we can't run 100 threads at the same time in parallel +this causes something known as context switching: cpu cores need to switch between threads +and this continuous switching would make the program slow + + +cpu cores have their own distinct cache, when a core changes a synced variable all the cpu cores change their cache value of that variable +when we have too many threads working on a synced variable, cpu cores constantly follow the changes in order to keep their cache synced +this would cause cpu cores to spend more time synchronizing the cache rather than processing the threads +this situation is known cache coherence synchronization overhead. + +## Q6 +Deadlocks are rare because you can't determine threads execution order, OS determines this by itself +to increase likelihood of deadlocks to happen a developer can start too many threads and delay the threads \ No newline at end of file diff --git a/src/main/java/bonus/AtomicVsNormal.java b/src/main/java/bonus/AtomicVsNormal.java new file mode 100644 index 0000000..8a5aa08 --- /dev/null +++ b/src/main/java/bonus/AtomicVsNormal.java @@ -0,0 +1,42 @@ +package bonus; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +public class AtomicVsNormal { + private static int counter = 0; + private static AtomicInteger atomicCounter = new AtomicInteger(0); + + public static void main(String[] args){ + int incrementCount = 1000; + List workers = new ArrayList<>(); + + for (int i = 0; i < 10; i++){ + workers.add(new Thread(() ->{ + for (int j = 0; j < incrementCount; j++) { + counter++; + atomicCounter.incrementAndGet(); + } + } + )); + } + + for (Thread worker : workers){ + worker.start(); + } + + for (Thread worker : workers){ + try { + worker.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + System.out.println("Expected: 10000"); + System.out.println("Normal increment: " + counter); + System.out.println("Atomic increment: " + atomicCounter.get()); + + } +} -- 2.54.0 From 2f1a3bee23aedeb1979e29b9da78c5d82c9e4ff4 Mon Sep 17 00:00:00 2001 From: Farnam Jahangard Date: Thu, 11 Jun 2026 17:53:27 +0330 Subject: [PATCH 2/2] implemented methods in BankAccount.java passed all the tests --- .../java/dev/banking/model/BankAccount.java | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/main/java/dev/banking/model/BankAccount.java b/src/main/java/dev/banking/model/BankAccount.java index 745ede2..fbfa154 100644 --- a/src/main/java/dev/banking/model/BankAccount.java +++ b/src/main/java/dev/banking/model/BankAccount.java @@ -1,10 +1,14 @@ package dev.banking.model; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + public class BankAccount { private final int accountId; private long balance; - + private final Lock lock = new ReentrantLock(); /* * Students may introduce additional fields * such as: @@ -32,7 +36,13 @@ 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.lock(); + try { + return balance; + } + finally { + lock.unlock(); + } } /* @@ -43,7 +53,13 @@ public class BankAccount { * - Must not lose updates under concurrency */ public void deposit(long amount) { - throw new UnsupportedOperationException("TODO: implement thread-safe deposit"); + lock.lock(); + try{ + balance += amount; + } + finally { + lock.unlock(); + } } /* @@ -56,7 +72,13 @@ public class BankAccount { * to extend the system (optional) */ public void withdraw(long amount) { - throw new UnsupportedOperationException("TODO: implement thread-safe withdraw"); + lock.lock(); + try { + balance -= amount; + } + finally { + lock.unlock(); + } } /* @@ -73,6 +95,19 @@ public class BankAccount { * - Or tryLock with retry strategy */ public void transfer(BankAccount target, long amount) { - throw new UnsupportedOperationException("TODO: implement atomic deadlock-free transfer"); + BankAccount first = this.getAccountId() > target.getAccountId() ? target : this; + BankAccount second = this.getAccountId() > target.getAccountId() ? this : target; + + first.lock.lock(); + second.lock.lock(); + try { + this.balance -= amount; + target.balance += amount; + } + finally { + second.lock.unlock(); + first.lock.unlock(); + } + } } \ No newline at end of file -- 2.54.0