Deadlock in Java MultithreadingLast Updated : 21 Jan 2026 Deadlock in Java Multithreading is a critical concurrency problem where two or more threads get permanently blocked while waiting for resources held by each other. In this chapter, we will understand what deadlock is, how it occurs in Java multithreading, its necessary conditions with examples. How Deadlock Occurs in Java Multithreading?Deadlock is a condition in multithreading that occurs when two or more threads are permanently blocked because each thread is waiting for a lock held by another thread. Since none of the threads can proceed until the required lock is released, they remain stuck waiting for each other, resulting in a deadlock. ![]() Necessary Conditions for Deadlock in MultithreadingThese are the four necessary conditions that must be present for a deadlock to occur in multithreading:
Example of Deadlock in Java MultithreadingThe following Java program demonstrates a deadlock situation where two threads attempt to acquire two shared resources in opposite order that causes both threads to wait indefinitely for each other. ExampleCompile and RunOutput: Thread 1: locked resource 1 Thread 2: locked resource 2 Explanation There are two resources: resource1 and resource2. First thread t1 locks the resource1 and sleeps. Similarly, the second thread, t2, locks resource2 and sleeps. Each thread sleeps for 100 milliseconds. After that, the first thread, t1, tries to acquire resource2, and the second thread, t2, tries to acquire resource1. However, resource1 is acquired by thread t1, and resource2 is acquired by thread t2, resulting in a deadlock situation, and the same is evident from the output. The second and fourth print statements do not execute. More Complicated DeadlocksDeadlocks are not limited to just two threads. In complex applications, a deadlock can involve multiple threads and resources that makes it harder to detect and resolve. Example of a Multi-Thread Deadlock ScenarioConsider the following situation involving four threads:
In this case, each thread is waiting for a resource held by another thread, forming a circular dependency. As a result, none of the threads can proceed, and the system enters a deadlock state. Deadlocks DetectionJava provides command-line tools that help detect deadlocks in running applications. Follow the steps below to identify a deadlock. Step 1: Compile and Run the ProgramCompile and execute the Java program that contains a deadlock using the following commands: At this stage, the program will appear to be running indefinitely due to the deadlock. ![]() Step 2: Find the Java Process IDOpen a new command prompt window and execute: This command lists all running Java processes along with their process IDs (PID). ![]() Locate the process running your program (for example, Main) and note its PID (e.g., 8680). Step 3: Print Thread InformationRun the following command by replacing This command generates a full thread dump of the Java process. ![]() Output:
8680:
2025-04-03 13:46:30
Full thread dump Java HotSpot(TM) 64-Bit Server VM (12.0.2+10 mixed mode, sharing):
Threads class SMR info:
_java_thread_list=0x000000ddaf977c70, length=12, elements={
0x000000ddae6d0000, 0x000000ddae6d1000, 0x000000ddae6e9800, 0x000000ddae6f0800,
0x000000ddae6f1800, 0x000000ddae6f5800, 0x000000ddae6f8800, 0x000000ddaf911000,
0x000000ddaf95b000, 0x000000ddaf976000, 0x000000ddaf976800, 0x000000dd8f70f800
}
"Reference Handler" #2 daemon prio=10 os_prio=2 cpu=0.00ms elapsed=448.77s tid=0x000000ddae6d0000 nid=0x5e68 waiting on condition [0x000000ddaf14f000]
java.lang.Thread.State: RUNNABLE
at java.lang.ref.Reference.waitForReferencePendingList(java.base@12.0.2/Native Method)
at java.lang.ref.Reference.processPendingReferences(java.base@12.0.2/Reference.java:241)
at java.lang.ref.Reference$ReferenceHandler.run(java.base@12.0.2/Reference.java:213)
"Finalizer" #3 daemon prio=8 os_prio=1 cpu=0.00ms elapsed=448.77s tid=0x000000ddae6d1000 nid=0x29ac in Object.wait() [0x000000ddaf24e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(java.base@12.0.2/Native Method)
- waiting on <0x000000008a90af78> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base@12.0.2/ReferenceQueue.java:155)
- locked <0x000000008a90af78> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base@12.0.2/ReferenceQueue.java:176)
at java.lang.ref.Finalizer$FinalizerThread.run(java.base@12.0.2/Finalizer.java:170)
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 cpu=0.00ms elapsed=448.77s tid=0x000000ddae6e9800 nid=0x5220 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Attach Listener" #5 daemon prio=5 os_prio=2 cpu=0.00ms elapsed=448.77s tid=0x000000ddae6f0800 nid=0x52d8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 cpu=15.63ms elapsed=448.77s tid=0x000000ddae6f1800 nid=0x1c4 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
No compile task
"C1 CompilerThread0" #8 daemon prio=9 os_prio=2 cpu=0.00ms elapsed=448.77s tid=0x000000ddae6f5800 nid=0x5338 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
No compile task
"Sweeper thread" #9 daemon prio=9 os_prio=2 cpu=0.00ms elapsed=448.77s tid=0x000000ddae6f8800 nid=0x5e70 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Service Thread" #10 daemon prio=9 os_prio=0 cpu=0.00ms elapsed=448.76s tid=0x000000ddaf911000 nid=0x3040 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Common-Cleaner" #11 daemon prio=8 os_prio=1 cpu=0.00ms elapsed=448.75s tid=0x000000ddaf95b000 nid=0x888 in Object.wait() [0x000000ddaff2e000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(java.base@12.0.2/Native Method)
- waiting on <0x000000008a9e7440> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base@12.0.2/ReferenceQueue.java:155)
- locked <0x000000008a9e7440> (a java.lang.ref.ReferenceQueue$Lock)
at jdk.internal.ref.CleanerImpl.run(java.base@12.0.2/CleanerImpl.java:148)
at java.lang.Thread.run(java.base@12.0.2/Thread.java:835)
at jdk.internal.misc.InnocuousThread.run(java.base@12.0.2/InnocuousThread.java:134)
"Thread-0" #12 prio=5 os_prio=0 cpu=0.00ms elapsed=448.75s tid=0x000000ddaf976000 nid=0x2100 waiting for monitor entry [0x000000ddb002f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at Main$1.run(Main.java:15)
- waiting to lock <0x000000008a800800> (a java.lang.String)
- locked <0x000000008a800000> (a java.lang.String)
"Thread-1" #13 prio=5 os_prio=0 cpu=0.00ms elapsed=448.75s tid=0x000000ddaf976800 nid=0x593c waiting for monitor entry [0x000000ddb012f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at Main$2.run(Main.java:30)
- waiting to lock <0x000000008a800000> (a java.lang.String)
- locked <0x000000008a800800> (a java.lang.String)
"DestroyJavaVM" #14 prio=5 os_prio=0 cpu=31.25ms elapsed=448.75s tid=0x000000dd8f70f800 nid=0x5db4 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"VM Thread" os_prio=2 cpu=0.00ms elapsed=448.78s tid=0x000000ddae6c9000 nid=0x5da4 runnable
"GC Thread#0" os_prio=2 cpu=0.00ms elapsed=448.78s tid=0x000000dd8f750000 nid=0x5b84 runnable
"G1 Main Marker" os_prio=2 cpu=0.00ms elapsed=448.78s tid=0x000000dd8f75d800 nid=0x1134 runnable
"G1 Conc#0" os_prio=2 cpu=0.00ms elapsed=448.78s tid=0x000000dd8f760000 nid=0x3624 runnable
"G1 Refine#0" os_prio=2 cpu=0.00ms elapsed=448.78s tid=0x000000dd8f7fa800 nid=0x56b8 runnable
"G1 Young RemSet Sampling" os_prio=2 cpu=0.00ms elapsed=448.78s tid=0x000000dd8f7fb800 nid=0x2464 runnable
"VM Periodic Task Thread" os_prio=2 cpu=0.00ms elapsed=448.75s tid=0x000000ddaf959800 nid=0x19bc waiting on condition
JNI global refs: 4, weak refs: 0
Found one Java-level deadlock:
=============================
"Thread-0":
waiting to lock monitor 0x000000ddae6db280 (object 0x000000008a800800, a java.lang.String),
which is held by "Thread-1"
"Thread-1":
waiting to lock monitor 0x000000ddae6d9280 (object 0x000000008a800000, a java.lang.String),
which is held by "Thread-0"
Java stack information for the threads listed above:
===================================================
"Thread-0":
at Main$1.run(Main.java:15)
- waiting to lock <0x000000008a800800> (a java.lang.String)
- locked <0x000000008a800000> (a java.lang.String)
"Thread-1":
at Main$2.run(Main.java:30)
- waiting to lock <0x000000008a800000> (a java.lang.String)
- locked <0x000000008a800800> (a java.lang.String)
Found 1 deadlock.
We can see that the output says Found 1 deadlock. Deadlock Detection OutputIn the thread dump output, Java clearly reports the deadlock with a message similar to: It also shows which threads are involved, the resources they are holding, and the resources they are waiting for. This confirms the presence of a deadlock. Preventing DeadlockDeadlocks should be addressed at their root cause. In most cases, inconsistent ordering of resource acquisition leads to deadlocks. The simplest way to prevent deadlocks is to ensure that all threads acquire shared resources in the same order. Example: Avoiding DeadlockThe following Java program demonstrates how deadlock can be avoided by acquiring resources in a consistent order. Output: In block 1 In block 2 Explanation In the above program, there are two threads, t1 and t2. After both the threads are spawned, thread t1 acquires resource b and sleeps for 100 milliseconds. Meanwhile, thread t2 also tries to acquire resource b, and since it is already acquired by thread t1, thread t2 waits. After that, thread t1 wakes from sleep, applies a lock on resource a, and then finishes its execution. Thus, releasing both resources, a and b. Thread t2 now acquires resource b and then resource a and does its job. Note that both threads do their task. Hence, there is no deadlock. How Deadlock Is Avoided in the Above Program
How to Avoid Deadlocks?Deadlocks cannot be completely eliminated, but they can be minimized by following these best practices:
Important Points About DeadlockThe following points list the common causes of deadlocks and best practices to detect, prevent, and manage them in multithreaded applications:
Next TopicInter-thread-communication-in-java |
We request you to subscribe our newsletter for upcoming updates.