Java Deadlock Example
In this article, we are going to show a Deadlock example in Java.
1. Introduction
In Java deadlock is defined as a scenario where two or more threads are blocked forever. A computer system normally has many active processes and threads. This is true even in systems that only have a single execution core, and thus only have one thread actually executing at any given moment. Processing time for a single core is shared among processes and threads through an OS feature called time slicing.
Threads are sometimes called lightweight processes. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process. Threads exist within a process. Every process has at least one. Threads share the process’s resources, including memory and open files. This makes for efficient, but potentially problematic, communication.
2. Java Deadlock Example
In this section, we will see how to create a scenario where a deadlock can happen. We will create two lock objects which we will use for locking.
private static Object lock1 = new Object(); private static Object lock2 = new Object();
We will start by creating a simple Thread
.
Thread1.java
private static class Thread1 extends Thread { @Override public void run() { synchronized (lock1) { System.out.println("Thread1 is holding lock1"); try { Thread.sleep(100); } catch (InterruptedException e) { } System.out.println("Thread1 is trying to obtain lock2..."); synchronized (lock2) { System.out.println("Thread1 is holding lock2"); } } } }
The first thing this thread will do is get a lock on lock1
object synchronized (lock1)
. Then we will let the sleep for 100 ms. After that this thread will try to get a lock on lock2
object.
Now we will see how the second Thread class looks like.
Thread2.java
private static class Thread2 extends Thread { @Override public void run() { synchronized (lock2) { System.out.println("Thread2 is holding lock2"); try { Thread.sleep(100); } catch (InterruptedException e) { } System.out.println("Thread2 is trying to obtain lock1..."); synchronized (lock1) { System.out.println("Thread2 is holding lock1"); } } } }
As we can see here that the second thread first tries to get a lock on lock2 object then sleep for 100 ms then try to get a lock on lock1 object. The sequence of getting the lock is opposite to Thread1
.
Now let us see how the main method looks like:
public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); thread2.start(); }
So when we run this class there is a good chance we will end up in a deadlock. Thread1
will get the lock on lock1
object then goes to sleep. Before it is awake thread2
will get a lock on lock2
. Now when thread1
awakes it will try to get the lock on lock2
object but thread2
is holding that lock. Thread2
can’t release the lock on lock2
as to do that it needs to get a lock on lock1
object which is locked by thread1.
So both the threads are waiting for the locks which the other thread has. So we have a deadlock situation here.
DeadlockExample.java
public class DeadlockExample { private static Object lock1 = new Object(); private static Object lock2 = new Object(); public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); thread2.start(); } private static class Thread1 extends Thread { @Override public void run() { synchronized (lock1) { System.out.println("Thread1 is holding lock1"); try { Thread.sleep(100); } catch (InterruptedException e) { } System.out.println("Thread1 is trying to obtain lock2..."); synchronized (lock2) { System.out.println("Thread1 is holding lock2"); } } } } private static class Thread2 extends Thread { @Override public void run() { synchronized (lock2) { System.out.println("Thread2 is holding lock2"); try { Thread.sleep(100); } catch (InterruptedException e) { } System.out.println("Thread2 is trying to obtain lock1..."); synchronized (lock1) { System.out.println("Thread2 is holding lock1"); } } } } }
When you will run this class you will se an output like below:
Thread2 is holding lock2 Thread1 is holding lock1 Thread2 is trying to obtain lock1... Thread1 is trying to obtain lock2...
If you do a thread dump you will see that the state of the treads are blocked
Thread0 dump:
"Thread-0" #12 prio=5 os_prio=31 cpu=0.99ms elapsed=4.79s tid=0x00007fd5a886b000 nid=0x9a03 waiting for monitor entry [0x000070000e2a2000] java.lang.Thread.State: BLOCKED (on object monitor) at com.javacodegeeks.DeadlockExample$Thread1.run(DeadlockExample.java:29) - waiting to lock (a java.lang.Object) - locked (a java.lang.Object)
Thread1 dump:
"Thread-1" #13 prio=5 os_prio=31 cpu=0.66ms elapsed=4.79s tid=0x00007fd5aa009000 nid=0x9703 waiting for monitor entry [0x000070000e3a5000] java.lang.Thread.State: BLOCKED (on object monitor) at com.javacodegeeks.DeadlockExample$Thread2.run(DeadlockExample.java:49) - waiting to lock (a java.lang.Object) - locked (a java.lang.Object)
3. Summary
In this article, we learned what is a deadlock and how it can occur in Java. We also learned how a Thread is different from a Process. Finally, we showed a working example where we created a scenario where a deadlock can occur.
4. Download the Source Code
This was an example of Java Deadlock.
You can download the full source code of this example here: Java Deadlock Example