Handling Thread Deadlock in Java

What is a Deadlock?

Deadlock is a situation that arises in case of two or more threads blocking each other’s resources while waiting for one at the same time. This condition emerges when various threads require the same resources which are acquired by one another.

Now, Before moving further into deadlocks, you need to require the basic understanding of the Java language. As currently Java is being used in various applications (from standalone to complex machine learning based) and mobile application. It has created numerous opportunities for freshers and experts in various fields such as mobile app development, gaming, robotics, etc. One can go through the Java Certification training courses, videos, blogs, and various other resources to explore development from a ground level. Thus, they can deliver more effective results in their respected field.

In java multithreading program, situations like deadlock are very common since synchronized keywords block the running thread when it waits for the lock.

In an operating system, a process handles resources in the following manner:

It requests for a resource
It uses that resource once acquired
It releases that resource

It can be easily understood with a real-world example of two cars running on the same single track. They both can’t move further as they are in front of one another.

The same situation occurs in case of thread two or more processes keeps resources and wait for each other’s resources.

Example :
The figure below demonstrates that thread A is holding resource 1 and demands for the resource 2.Similarly, thread B keeps resource 2, and it requires resource 1.

Both of these threads are making the deadlock scenario here.

DeadLock
TestDeadlockExample1.java

  1. public class TestDeadlockExample1 {  
  2.   public static void main(String[] args) {  
  3.     final String resource1 = "ratan jaiswal";  
  4.     final String resource2 = "vimal jaiswal";  
  5.     // t1 tries to lock resource1 then resource2  
  6.     Thread t1 = new Thread() {  
  7.       public void run() {  
  8.           synchronized (resource1) {  
  9.            System.out.println("Thread 1: locked resource 1");  
  10.  
  11.            try { Thread.sleep(100);} catch (Exception e) {}  
  12.  
  13.            synchronized (resource2) {  
  14.             System.out.println("Thread 1: locked resource 2");  
  15.            }  
  16.          }  
  17.       }  
  18.     };  
  19.  
  20.     // t2 tries to lock resource2 then resource1  
  21.     Thread t2 = new Thread() {  
  22.       public void run() {  
  23.         synchronized (resource2) {  
  24.           System.out.println("Thread 2: locked resource 2");  
  25.  
  26.           try { Thread.sleep(100);} catch (Exception e) {}  
  27.  
  28.           synchronized (resource1) {  
  29.             System.out.println("Thread 2: locked resource 1");  
  30.           }  
  31.         }  
  32.       }  
  33.     };  
  34.  
  35.      
  36.     t1.start();  
  37.     t2.start();  
  38.   }  
  39. }  
public class TestDeadlockExample1 {  
  public static void main(String[] args) {  
    final String resource1 = "ratan jaiswal";  
    final String resource2 = "vimal jaiswal";  
    // t1 tries to lock resource1 then resource2  
    Thread t1 = new Thread() {  
      public void run() {  
          synchronized (resource1) {  
           System.out.println("Thread 1: locked resource 1");  
  
           try { Thread.sleep(100);} catch (Exception e) {}  
  
           synchronized (resource2) {  
            System.out.println("Thread 1: locked resource 2");  
           }  
         }  
      }  
    };  
  
    // t2 tries to lock resource2 then resource1  
    Thread t2 = new Thread() {  
      public void run() {  
        synchronized (resource2) {  
          System.out.println("Thread 2: locked resource 2");  
  
          try { Thread.sleep(100);} catch (Exception e) {}  
  
          synchronized (resource1) {  
            System.out.println("Thread 2: locked resource 1");  
          }  
        }  
      }  
    };  
  
      
    t1.start();  
    t2.start();  
  }  
}  


On executing this code, it will create a deadlock situation as discussed in the above scenario.

Why deadlock occurs ?


Below is the necessary condition for a deadlock occurrence:

Mutual Exclusion: In this case, one or more than a resource is kept non-sharable. Thus, only one thread can use at a time.

No Preemption: A resource can’t be used until it is released by the process using it at that time.

Circular Wait: Group of processes waiting for one another’s resources in a circular form.

Hold and Wait: A process is using one resource keeping lock at it, while at the same time waiting for other resources.

How to Handle the Deadlock condition ?

Avoid Deadlock:

The first method is not to allow your program to enter into a deadlock situation.

Identification and Recovery: Once you encounter a deadlock, perform preemption to handle it smoothly.

Ignore all: If the deadlock is very common then allow it to happen. Reboot your program or system.

Resolution to deadlock:

I think this situation can be handled by recognizing the key problems.
In above-discussed case, the way both the resources are getting accessed is the main reason behind deadlock.

So, it requires just a little rearrangement of the resource while accessing them.

  1. // first thread
  2.  
  3. //thread communication
  4.  
  5. class Customer{  
  6. int amount=10000;    
  7. synchronized void withdraw(int amount){  
  8. System.out.println("Going To Withdraw...");  
  9. if(this.amount<amount){  
  10. System.out.println("Less Balance; Waiting For Deposit...");  
  11. try{wait();}catch(Exception e){}  
  12. }  
  13. this.amount-=amount;  
  14. System.out.println("Yeah! Withdraw Completed...");  
  15. }    
  16. synchronized void deposit(int amount){  
  17. System.out.println("Going To Deposit...");  
  18. this.amount+=amount;  
  19. System.out.println("Deposit Completed... ");  
  20. notify();  
  21. }  
  22. }  
  23.  
  24. class Test{  
  25. public static void main(String args[]){  
  26. final Customer c=new Customer();  
  27. new Thread(){  
  28. public void run(){c.withdraw(15000);}  
  29. }.start();  
  30. new Thread(){  
  31. public void run(){c.deposit(10000);}  
  32. }.start();    
  33. }}
// first thread 

//thread communication

class Customer{  
int amount=10000;    
synchronized void withdraw(int amount){  
System.out.println("Going To Withdraw...");  
if(this.amount<amount){  
System.out.println("Less Balance; Waiting For Deposit...");  
try{wait();}catch(Exception e){}  
}  
this.amount-=amount;  
System.out.println("Yeah! Withdraw Completed...");  
}    
synchronized void deposit(int amount){  
System.out.println("Going To Deposit...");  
this.amount+=amount;  
System.out.println("Deposit Completed... ");  
notify();  
}  
}  
 
class Test{  
public static void main(String args[]){  
final Customer c=new Customer();  
new Thread(){  
public void run(){c.withdraw(15000);}  
}.start();  
new Thread(){  
public void run(){c.deposit(10000);}  
}.start();    
}} 

Again, execute this code, and you will see it running without any deadlock. Thus, you can

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on