Skip to main content

Oops I Locked It Again! — My JVM’s Deadlock Love Story ๐Ÿ’”

๐Ÿ’€ What is Deadlock in Java?

Deadlock is like two people playing “You go first” forever. Neither gives up. Neither moves. JVM says: “I'm outta here.” ๐Ÿ˜ฉ

๐Ÿ”„ Real-World Analogy

๐Ÿ‘จ‍๐Ÿ’ผ Thread A grabs the Pen, waits for Paper
๐Ÿ‘ฉ‍๐Ÿ’ผ Thread B grabs the Paper, waits for Pen
Result: Both stuck — staring at each other ๐Ÿ‘€
Outcome: Deadlock! ☠️

⚙️ Java Code Example – How Deadlock Happens



public class DeadlockExample {

    private static final Object resourceA = new Object();

    private static final Object resourceB = new Object();

    public static void main(String[] args) {

        Thread t1 = new Thread(() -> {

            synchronized (resourceA) {

                System.out.println("Thread-1 locked Resource A");

                try { Thread.sleep(100); } catch (Exception ignored) {}

                synchronized (resourceB) {

                    System.out.println("Thread-1 locked Resource B");

                }

            }

        });

        Thread t2 = new Thread(() -> {

            synchronized (resourceB) {

                System.out.println("Thread-2 locked Resource B");

                try { Thread.sleep(100); } catch (Exception ignored) {}

                synchronized (resourceA) {

                    System.out.println("Thread-2 locked Resource A");

                }

            }

        });

        t1.start();

        t2.start();

    }

}

๐ŸŽจ Diagrammatic Representation


Time T0:

Thread-1: LOCKS resourceA ๐Ÿ”

Thread-2: LOCKS resourceB ๐Ÿ”

Time T1:

Thread-1: WAITING for resourceB (held by Thread-2) ⏳

Thread-2: WAITING for resourceA (held by Thread-1) ⏳

=> Neither can proceed = DEADLOCK ☠️

๐Ÿ” What is ReentrantLock?

Java’s ReentrantLock is part of the java.util.concurrent.locks package and gives more control than synchronized.

✅ Benefits:

  • Try lock with timeout ⏲️
  • Interrupt lock waiting
  • Fairness option (FIFO)

๐Ÿงช Example: Avoiding Deadlock with tryLock()



import java.util.concurrent.locks.*;

public class DeadlockFree {

    private static final Lock lockA = new ReentrantLock();

    private static final Lock lockB = new ReentrantLock();

    public static void main(String[] args) {

        Thread t1 = new Thread(() -> {

            try {

                if (lockA.tryLock(100, TimeUnit.MILLISECONDS)) {

                    try {

                        if (lockB.tryLock(100, TimeUnit.MILLISECONDS)) {

                            try {

                                System.out.println("Thread-1 got both locks");

                            } finally {

                                lockB.unlock();

                            }

                        }

                    } finally {

                        lockA.unlock();

                    }

                }

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        });

        Thread t2 = new Thread(() -> {

            try {

                if (lockB.tryLock(100, TimeUnit.MILLISECONDS)) {

                    try {

                        if (lockA.tryLock(100, TimeUnit.MILLISECONDS)) {

                            try {

                                System.out.println("Thread-2 got both locks");

                            } finally {

                                lockA.unlock();

                            }

                        }

                    } finally {

                        lockB.unlock();

                    }

                }

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        });

        t1.start();

        t2.start();

    }

}

๐Ÿ“Š In-Depth: When and How Deadlock Can Happen

Deadlock can only occur if all 4 conditions happen together.

๐Ÿ”’ 1. Mutual Exclusion

  • What it means: Only one thread can use a resource at a time
  • Code example:


synchronized(resourceA) {

   // only one thread inside

}

✅ You can't avoid it — but you can manage it with order & timeouts

๐Ÿ™‹‍♂️ 2. Hold and Wait

  • What it means: Thread holds one lock, waits for another
  • Code example:


synchronized(resourceA) {

    Thread.sleep(100);

    synchronized(resourceB) {

       // waiting for B while holding A

    }

}

✅ Solution: Lock both at once or use tryLock()

✅ Try-Lock Solution



if (lockA.tryLock(100, TimeUnit.MILLISECONDS)) {

    if (lockB.tryLock(100, TimeUnit.MILLISECONDS)) {

        // Got both safely

    }

}

๐Ÿšซ 3. No Preemption

  • What it means: JVM won't take a lock back forcibly
  • Problem: If thread holds a lock too long, others are stuck

✅ Solution: Always use finally to release lock and prefer tryLock()

๐Ÿ”„ 4. Circular Wait

  • What it means: Threads form a circle of dependency


// Thread 1

synchronized(A) {

    synchronized(B) {

        // ...

    }

}

// Thread 2

synchronized(B) {

    synchronized(A) {

        // ...

    }

}

✅ Solution: Lock Ordering



Object[] locks = {resourceA, resourceB};

Arrays.sort(locks, Comparator.comparing(Object::hashCode));

synchronized(locks[0]) {

    synchronized(locks[1]) {

        // safe section

    }

}

✅ All 4 conditions met = Guaranteed Deadlock ☠️

✅ Prevention Strategies Recap

✅ Strategy ๐Ÿ’ก Benefit
๐Ÿ” Lock in Same Order Avoids circular wait
⏲️ Use tryLock() Prevents infinite waiting
๐Ÿงผ Avoid Nested Locks Keeps logic simple
๐Ÿงช Use Thread Dumps Detect stuck threads (jstack, VisualVM, JFR)
☁️ Split Big Locks Reduces contention

๐Ÿ˜… Java Joke Break

๐Ÿง‘‍๐Ÿ’ป Developer: "Why does my program hang at night?"
๐Ÿ‘ป Deadlock: "Because I’m locking your dreams too."

๐ŸŽฏ Final Tip

Deadlock doesn't throw an exception. It silently kills performance. Watch for signs like:

  • High CPU usage ๐Ÿ”ฅ
  • No logs output ๐Ÿ•ณ️
  • Thread dumps showing "waiting to lock" ๐Ÿ”

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...