Skip to main content

๐Ÿ’ฃ Without Thread Safety — Chaos in Banking

๐ŸŽฏ 1. Setting the Scene — The Interview Moment

Imagine this…

Interviewer: “So, how would you handle multiple threads accessing a shared bank account in Java?”
Me: “You mean… like multiple ATMs punching the same account balance at the same time?” ๐Ÿฆ๐Ÿ’ณ
Interviewer: smiles like a villain in a heist movie ๐Ÿ˜ˆ “Exactly.”

๐Ÿšจ 2. Without Thread Safety — What Happens?

Bad Code (Singleton Bean or Shared Object)

class BankAccount {
    private int balance = 1000; // Shared among threads

    public void deposit(int amount) {
        balance += amount; // ๐Ÿšจ Not synchronized
        System.out.println(Thread.currentThread().getName()
            + " deposited ₹" + amount + ", Balance: ₹" + balance);
    }

    public void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount; // ๐Ÿšจ Not synchronized
            System.out.println(Thread.currentThread().getName()
                + " withdrew ₹" + amount + ", Balance: ₹" + balance);
        } else {
            System.out.println(Thread.currentThread().getName()
                + " tried to withdraw ₹" + amount + " but insufficient balance!");
        }
    }
}

public class BankTest {
    public static void main(String[] args) {
        BankAccount account = new BankAccount();

        Thread t1 = new Thread(() -> {
            account.deposit(500);
            account.withdraw(200);
        }, "ATM-1");

        Thread t2 = new Thread(() -> {
            account.withdraw(300);
            account.deposit(400);
        }, "ATM-2");

        t1.start();
        t2.start();
    }
}

๐Ÿ’ฅ The Problem

balance is a class-level variable shared between all threads.

Threads run in parallel, so:

  • ATM-1 reads balance = 1000, adds 500 → 1500 (temporarily in its CPU cache).
  • ATM-2 at the same time reads balance = 1000, subtracts 300 → 700.
  • The writes overwrite each other → lost updates.

๐Ÿ–ผ Diagram — Without Thread Safety

   Shared BankAccount object (Heap Memory)
   ---------------------------------------
   balance = 1000

    ATM-1 Thread               ATM-2 Thread
    -----------                -----------
    Reads balance=1000         Reads balance=1000
    +500 = 1500                -300 = 700
    Writes 1500                Writes 700
           ❌ 1500 lost, final balance = 700

This is called a race condition — threads racing to update the same variable.

๐Ÿ›ก️ 3. Making It Thread-Safe

Fix 1 — synchronized keyword

class BankAccount {
    private int balance = 1000;

    public synchronized void deposit(int amount) {
        balance += amount;
        System.out.println(Thread.currentThread().getName()
            + " deposited ₹" + amount + ", Balance: ₹" + balance);
    }

    public synchronized void withdraw(int amount) {
        if (balance >= amount) {
            balance -= amount;
            System.out.println(Thread.currentThread().getName()
                + " withdrew ₹" + amount + ", Balance: ₹" + balance);
        } else {
            System.out.println(Thread.currentThread().getName()
                + " tried to withdraw ₹" + amount + " but insufficient balance!");
        }
    }
}

๐Ÿ’ก Why it works:

  • synchronized ensures only one thread at a time executes the method on that object.
  • Prevents overlapping reads/writes.

๐Ÿ–ผ Diagram — With synchronized

   Shared BankAccount object (Heap Memory)
   ---------------------------------------
   balance = 1000

    ATM-1 Thread --------------|
                               |  Lock acquired
    Updates balance safely     |
                               |  Lock released
                               |
    ATM-2 Thread --------------|
    Waits until ATM-1 finishes

Fix 2 — Database Transactions (Real World)

If this were a microservice, thread safety in code is not enough —
you’d need transaction isolation in the database so even if multiple service instances run, updates happen safely.

Fix 3 — @RequestScope or @Prototype

Works only if each request has its own account object (like a form or cart).
❌ Doesn’t work for real banking balances, because balances are shared globally.

๐Ÿ“š 4. Learning Takeaway

“Threads are like customers at an ATM — if you don’t control access, one will take your money while another is counting it.” ๐Ÿ’ฐ

Key Points:

  • Class-level variables in singleton beans are shared → not thread-safe.
  • Local method variables are thread-safe by default (each thread has its own stack).
  • Use:
    • synchronized / Lock for in-memory protection.
    • Database locks for multi-instance services.
    • Scopes like @RequestScope only when state is per-request, not shared.

Comments

Popular posts from this blog

๐Ÿ” Is final Really Final in Java? The Truth May Surprise You ๐Ÿ˜ฒ

๐Ÿ’ฌ “When I was exploring what to do and what not to do in Java, one small keyword caught my eye — final . I thought it meant: locked, sealed, frozen — like my fridge when I forget to defrost it.”   But guess what? Java has its own meaning of final… and it’s not always what you expect! ๐Ÿ˜… Let’s break it down together — with code, questions, confusion, jokes, and everything in between. ๐ŸŽฏ The Confusing Case: You Said It's Final... Then It Changed?! ๐Ÿซ  final List<String> names = new ArrayList <>(); names.add( "Anand" ); names.add( "Rahul" ); System.out.println(names); // [Anand, Rahul] ๐Ÿคฏ Hold on... that’s final , right?! So how on earth is it still changing ? Time to dive deeper... ๐Ÿง  Why Is It Designed Like This? Here’s the key secret: In Java, final applies to the reference , not the object it points to . Let’s decode this like a spy mission ๐Ÿ•ต️‍♂️: Imagine This: final List<String> names = new ArrayList <>(); Be...

๐ŸŒŸ My Journey – From Zero to Senior Java Tech Lead ๐ŸŒŸ

 There’s one thing I truly believe… If I can become a Java developer, then anyone in the world can. ๐Ÿ’ฏ Sounds crazy? Let me take you back. ๐Ÿ•“ Back in 2015… I had zero coding knowledge . Not just that — I had no interest in coding either. But life has its own plans. In 2016, I got a chance to move to Bangalore and joined a Java course at a training center. That’s where it all started — Every day, every session made me feel like: "Ohhh! Even I can be a developer!" That course didn’t just teach Java — it gave me confidence . ๐Ÿงช Two Life-Changing Incidents 1️⃣ The Interview That Wasn't Planned Halfway through my course, I had to urgently travel to Chennai to donate blood to a family member. After that emotional rollercoaster, I found myself reflecting on my skills and the future. The next day, as I was preparing for my move to Bangalore to complete the remaining four months of my course, I randomly thought — "Let me test my skills... let me just see...

๐ŸŽข Java Loops: Fun, Fear, and ForEach() Fails

๐ŸŒ€ Oops, I Looped It Again! — The Ultimate Java Loop Guide You Won't Forget “I remember this question from one of my early interviews — I was just 2 years into Java and the interviewer asked, ‘Which loop do you prefer and why?’” At first, I thought, “Duh! for-each is cleaner.” But then he grilled me with cases where it fails. ๐Ÿ˜ต That led me to explore all loop types, their powers, and their pitfalls. Let’s deep-dive into every major Java loop with examples &  real-world guidance so you'll never forget again. ๐Ÿ” Loop Type #1: Classic For Loop — “The Old Reliable” ✅ When to Use: You need an index You want to iterate in reverse You want full control over loop mechanics ✅ Good Example: List<String> names = List.of("A", "B", "C"); for (int i = 0; i < names.size(); i++) { System.out.println(i + ": " + names.get(i)); } ๐Ÿ”ฅ Reverse + Removal Example: List<String> item...