Table of contents
1.
Introduction
2.
What is a Deadlock in Java?
3.
Why Deadlock Occurs in Java?
3.1.
Example of deadlock in Java
3.1.1.
Code
3.2.
Java
3.2.1.
Output
4.
Complex deadlocks
5.
Handling Deadlocks
5.1.
Code
5.2.
Java
5.3.
Output
6.
Ways To Avoid Deadlocks in Java
7.
Deadlock vs Livelock vs Starvation
7.1.
Deadlock
7.2.
Livelock
7.3.
Starvation
7.4.
Key Differences
8.
Frequently Asked Questions
8.1.
What is deadlock and its 4 types?
8.2.
What is an example of a deadlock?
8.3.
How to handle deadlock exceptions in Java?
8.4.
How can we avoid Deadlocks?
8.5.
Can we resolve a deadlock in Java?
9.
Conclusion
Last Updated: Jun 9, 2025
Easy

Deadlock in Java

Author Ankit Kumar
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Hello Ninjas! Learning Java? Got stuck in handling deadlocks? Don’t worry, we got you covered, as this article will make you learn everything about deadlocks in Java and also will discuss some of the tips to avoid deadlocks so that you can code freely.

Deadlock in Java

Before starting learning about the deadlock in Java, learn about Multithreading in Java.

In brief, Multithreading is the process of Java that makes two or more parts of the program execute parallely to make the utmost use of the CPU. Now let us learn about the deadlock in the next section.

What is a Deadlock in Java?

Deadlock in Java is a condition where two or more threads are blocked forever, each waiting for the other to release a lock. Deadlock occurs in multithreaded applications when threads try to acquire locks on resources in a circular manner, leading to a situation where none of the threads can proceed.

Read More About, Basics of Java

Why Deadlock Occurs in Java?

Deadlock in Java occurs when two or more threads are blocked forever, each waiting for the other to release a resource. This usually happens due to resource contention and improper synchronization in multithreaded programs. When multiple threads try to acquire locks on shared resources in an uncoordinated way, they can end up waiting indefinitely, causing the program to freeze.

Deadlock typically arises when the following four necessary conditions occur simultaneously:

  1. Mutual Exclusion: At least one resource must be held in a non-shareable mode.
  2. Hold and Wait: A thread holding a resource is waiting to acquire additional resources held by other threads.
  3. No Preemption: Resources cannot be forcibly taken from threads; they must be released voluntarily.
  4. Circular Wait: A set of threads are waiting on each other in a circular chain.

Example of deadlock in Java

Let us see a java code that portrays an example of the Deadlock condition in Java.

Code

  • Java

Java

// A java program to portray deadlock
public class DeadlockExample { 
 public static void main(String[] args) { 
   final String r1 = "Ankit kumar"; 
   final String r2 = "Aman shivhare"; 
   // Here Thread1 tries to lock r1 and then r2 
   Thread Thread1 = new Thread() { 
     public void run() { 
         synchronized (r1) { 
          System.out.println("Thread 1: locked r 1");   
try { Thread.sleep(100);} catch (Exception e) {} 

          synchronized (r2) { 
           System.out.println("Thread 1: locked 2"); 
          } 
        } 
     } 
   }; 
   // thread2 tries to lock r2 then r1 
   Thread Thread2 = new Thread() { 
     public void run() { 
       synchronized (r2) { 
         System.out.println("Thread 2: locked r 2"); 
         try { Thread.sleep(100);} catch (Exception e) {} 
         synchronized (r1) { 
           System.out.println("Thread 2: locked r1"); 
         } 
       } 
     } 
   };       
   Thread1.start(); 
   Thread2.start(); 
 } 
}  
You can also try this code with Online Java Compiler
Run Code

    

Output

Thread 1: locked r 1

Thread 2: locked r 2

The system enters into a deadlock situation in the above-quoted example.

Any system can also see some complex deadlock which not only involves two but more threads that are waiting for object locks that are acquired by other threads. They become more complicated, and eventually, they are hard to resolve. Let us see one such case.

Complex deadlocks

If any code in such a manner such that the following conditions mark true for them, then they are believed to be a complex deadlock!

Thread 1 locks X waits for Y

Thread 2 locks Y waits for Z

Thread 3 locks Z waits for W

Thread 4 locks W, waits for X

Here Thread 1 waits for thread 2, thread two waits for thread 3, thread three waits for thread 4, and thread four waits for thread 1.

So this was a case for a complex deadlock. Now the question arises here is how can we handle them? Let us answer this in the following section.

Handling Deadlocks

If we can somehow change the pattern or the order of the statements that are used to access the shared resources, then we can handle the simpler deadlocks easily. Let us see the code for it.

Code

  • Java

Java

// A java program to solve deadlock
public class Deadlock_Solved { 
   public static void main(String ar[]) { 
       Deadlock_Solved example = new Deadlock_Solved(); 
       final r1 x = example.new r1(); 
       final r2 y = example.new r2();  
  // Thread-1 
Runnable y1 = new Runnable() { 
   public void run() { 
       synchronized (y) { 
           try { 
               // Adding delay so that both threads can start trying to lock resources
               Thread.sleep(100); 
           } catch (InterruptedException e) { 
               e.printStackTrace(); 
           } 
           // Thread-1 do have resource1 but also need resource2  
           synchronized (x) { 
               System.out.println("In block 1"); 
           } 
       } 
   } 
};   
// Thread-2 
Runnable y2 = new Runnable() { 
   public void run() { 
       synchronized (y) { 
           // Thread-2 have resource2 but need resource1 also 
           synchronized (x) { 
               System.out.println("In block 2"); 
           } 
       } 
   } 
};
       new Thread(y1).start(); 
       new Thread(y2).start(); 
   } 
   // resource1 
   private class r1 { 
       private int p = 10; 
       public int getI() { 
           return p; 
       }
       public void setI(int p) { 
           this.p = p; 
       } 
   // resource2 
   }
   private class r2 { 
       private int p = 20; 
 
       public int getI() { 
           return p; 
       } 
       public void setI(int p) { 
           this.p = p; 
       } 
   } 
}
You can also try this code with Online Java Compiler
Run Code

Output

In block 1

In block 2

So this was how we handled the simple deadlock condition for two threads. But Solving the complex deadlock situation can be very challenging, so we need to avoid certain things which are discussed in the next section.

Try it by yourself on java online compiler.

Must Read Static Blocks In Java.

Ways To Avoid Deadlocks in Java

We simply cannot vanish the chances of the system attaining a deadlock situation, but if we follow certain ways, then we can avoid them to a greater extent.

  1. Avoid nested locks: Nested locks refer to a situation where a thread holds a lock on one resource and attempts to acquire a lock on another resource. When multiple threads are involved, this can quickly lead to a circular dependency, causing deadlock.
  2. Avoid unnecessary locks: Using more locks than required can complicate code and increase the chance of deadlock. Unnecessary locks can also reduce program efficiency, as threads may spend more time waiting on locks that aren’t essential.
  3. Using thread join: The Thread.join() method allows one thread to wait for the completion of another. This approach can help avoid deadlock by ensuring that threads complete their work in a specific order, reducing the chance of circular waiting.

With learning these techniques to avoid the possibility of a deadlock, we come to the end of this blog. Let us try to answer some of the FAQs related to this topic.

You can also read about the Multiple Inheritance in Java.

Deadlock vs Livelock vs Starvation

Deadlock

Deadlock occurs when two or more threads are permanently blocked, each waiting for resources held by the other. In this situation, none of the threads can proceed, and the program comes to a standstill. Deadlock usually happens due to improper lock ordering or poor resource management in multithreaded environments.
For example, if Thread A holds Lock 1 and waits for Lock 2, while Thread B holds Lock 2 and waits for Lock 1, both threads will wait forever.
Key Point: Threads are completely blocked and cannot continue.

Livelock

Livelock is a situation where threads remain active and constantly changing their states, but they are unable to make progress because they keep reacting to each other’s actions. Unlike deadlock, the threads are not stuck waiting; instead, they keep retrying operations without success.
For example, imagine two people continuously stepping aside to let each other pass in a narrow hallway, but neither gets through.
Key Point: Threads are not blocked but are stuck in an endless cycle without completing their tasks.

Starvation

Starvation occurs when a thread waits indefinitely for a resource because other threads are constantly given preference. This usually happens when lower-priority threads are repeatedly bypassed by higher-priority ones, or when resources are heavily contested.
For example, in a busy restaurant, a customer who always gets skipped by waiters serving other tables may never get served.
Key Point: A thread is ready to execute but is continuously ignored due to scheduling or priority rules.

Key Differences

FeatureDeadlockLivelockStarvation
Thread StatePermanently blockedActively running but stuckWaiting indefinitely
CauseCircular resource waitingConstant response to othersResource preference or priority
ProgressNoNoOther threads make progress
ExampleTwo threads holding locksTwo people stepping aside repeatedlyLow-priority thread never gets CPU time

 

  • Deadlock: Threads block each other.
  • Livelock: Threads keep working but achieve nothing.
  • Starvation: Threads are overlooked and never get resources.

Frequently Asked Questions

What is deadlock and its 4 types?

Deadlock is a situation where threads are indefinitely blocked, waiting for each other's resources. The types are mutual exclusion, hold and wait, no preemption, and circular wait.

What is an example of a deadlock?

A common deadlock example involves two threads, where each thread holds one lock and waits for a second lock held by the other.

How to handle deadlock exceptions in Java?

Java doesn't throw specific deadlock exceptions. To handle deadlocks, use lock ordering, tryLock() with timeouts, or detect circular dependencies in threads.

How can we avoid Deadlocks?

We can avoid deadlocks by avoiding the use of nested or some unnecessary locks and by using thread join.

Can we resolve a deadlock in Java?

Yes, we can resolve a deadlock condition in Java by simply reordering the statements that are used to access the shared resources.

Conclusion

In this article, we have extensively discussed deadlock in Java along with its example. We also saw many ways which can minimise the chance of any system getting into a deadlock situation. We saw two codes, one with the deadlock and the another after reordering the statements which were used to access the shared resources. In the end, we answered some of the frequently asked questions related to this topic.

Live masterclass