In Java, Deadlock is a situation of multithreading where thread 1 waits for an object lock attained by thread 2, and thread 2 waits for an object lock attained by thread 1. Here, both thread 1 and thread 2 wait for each other to release the lock. Multithreaded programs in Java can cause Deadlock as the keyword synchronized blocks the executing thread while waiting for a monitor or lock linked with the object mentioned. Let us see the working and examples of Deadlock in the following sections.
Start Your Free Software Development Course
Web development, programming languages, Software testing & others
As discussed, the synchronized method can lock a particular portion of the code. For each object in Java, a lock will be there, and Synchronization is a technique to lock a function or block of code to ensure that only 1 thread can access that function or block of code at a time.
When a specific thread needs to execute a synchronized function, it first attempts to obtain the lock. At the same time, if another thread has already received the lock, the first thread waits until thread 2 releases the lock. Even though Synchronization prevents issues with data inconsistency, there is a synchronization issue.
Assume there are 2 threads, ‘Thread 1’ and ‘Thread 2’. Thread 1 has attained the lock of Object 1, and Thread 2 has attained the lock of Object 2. Thread 1, which executes method 1, wants to attain the lock on Object 2. However, Thread 2 already attains the lock on Object 2.
In addition, Thread 2 also needs to attain the lock on Object 1; however, Thread 1 has a lock on Object 1. Here, both threads, Thread 1 and Thread 2, can’t complete their execution and wait for the lock forever. This situation is called Deadlock.
Given below are the examples mentioned:
Java program to implement Deadlock.
Code:
public class DeadLockExample { //main method public static void main(String[] args) throws InterruptedException { //create three objects 1, 2 and 3 Object o1 = new Object(); Object o2 = new Object(); Object o3 = new Object(); //create three threads 1, 2 and 3 Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1"); Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2"); Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3"); //start thread 1 th1.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); //start thread 2 th2.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); //start thread 3 th3.start(); } } class SynchronizationThread implements Runnable { private Object o1; private Object o2; public SynchronizationThread(Object o1, Object o2){ this.o1=o1; this.o2=o2; } //function run @Override public void run() { //store the name of the thread String nm = Thread.currentThread().getName(); System.out.println( nm + " attaining lock on "+ o1 ) ; synchronized (o1) { System.out.println( nm + " attained lock on "+ o1 ) ; work(); System.out.println( nm + " attaining lock on "+ o2 ) ; synchronized (o2) { System.out.println( nm + " attained lock on "+ o2 ); work(); } System.out.println( nm + " released lock on "+ o2 ) ; } System.out.println( nm + " released lock on "+ o1 ) ; System.out.println( nm + " completed execution.") ; } //function work private void work() { try { //thread sleeps Thread.sleep(30000); } //catch the exception catch (InterruptedException exc) { exc.printStackTrace(); } } }
Output:
In this program, 3 threads running share a resource, and they run in a way that attains lock on object 1, but when it tries to attain lock on object 2, it goes into a wait state. To prevent Deadlock, you can rewrite the code as follows.
Code:
public class DeadLockExample { public static void main(String[] args) throws InterruptedException { Object o1 = new Object(); Object o2 = new Object(); Object o3 = new Object(); Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1"); Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2"); Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3"); //start thread 1, 2 and 3 th1.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); th2.start(); //thread sleeps for 5000 seconds Thread.sleep(5000); th3.start(); } } class SynchronizationThread implements Runnable{ private Object o1; private Object o2; public SynchronizationThread(Object o1, Object o2){ this.o1=o1; this.o2=o2; } //function run @Override public void run() { //store the name of the thread String nm = Thread.currentThread().getName(); System.out.println( nm + " attaining lock on "+ o1 ) ; synchronized (o1) { System.out.println( nm + " attained lock on "+ o1 ) ; work(); } System.out.println( nm + " released lock on "+ o1 ) ; System.out.println( nm + " acquiring lock on " + o2 ); synchronized (o2) { System.out.println( nm + " attained lock on "+ o2 ); work(); } System.out.println( nm + " released lock on "+ o2 ) ; System.out.println( nm + " released lock on "+ o1 ) ; System.out.println( nm + " completed execution.") ; } //function work private void work() { try { //thread sleeps Thread.sleep(30000); } //catch the exception catch (InterruptedException exc) { exc.printStackTrace(); } } }
Output:
Following are the guidelines that help in avoiding deadlock situations.
Nested locks are one of the common reasons for causing deadlocks. Do not lock another resource if it already holds one to avoid Deadlock. If the user works with only 1 object, it is impossible to cause a deadlock.
People recommend locking only the necessary resources. However, some users may attempt to lock resources even when not required.
Deadlock occurs if 2 threads wait for each other to complete indefinitely with the help of thread join. If the thread needs to wait for other threads to complete, it is good to use join with the maximum amount of time that has to wait for the thread to complete.
The above is the detailed content of Deadlock in Java. For more information, please follow other related articles on the PHP Chinese website!