SrcForge

Lesson 52

Deadlock and Inter-Thread Communication

Deadlock occurs when threads wait on each other indefinitely; inter-thread communication uses wait(), notify(), and notifyAll() to coordinate thread execution efficiently.

Java Track

Save progress as you learn.

61 lessons

Lesson content

A deadlock in Java occurs when two or more threads wait indefinitely for each other to release resources, causing the program to stop progressing. Inter-thread communication is a mechanism that allows threads to coordinate their execution using methods such as wait(), notify(), and notifyAll().

Definition List

  • Deadlock: A condition where two or more threads wait indefinitely for locks held by each other.
  • Thread: A lightweight unit of execution within a Java application.
  • Lock: A mechanism used to control access to shared resources.
  • Synchronized Method: A method that allows only one thread to execute it at a time.
  • Resource: An object or shared data that multiple threads can access.

Deadlock Scenario

Thread A                 Thread B
   │                        │
Locks Resource A      Locks Resource B
   │                        │
Waits for B           Waits for A
   │                        │
   └───── Deadlock ─────────┘

Example: Java Deadlock

package com.java.Multi_threading;

public class DeadlockExample {

    static class Resource {

        public synchronized void method1(Resource anotherResource) {
            System.out.println(Thread.currentThread().getName() + " is executing method1()");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            anotherResource.method2(this);
        }

        public synchronized void method2(Resource anotherResource) {
            System.out.println(Thread.currentThread().getName() + " is executing method2()");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            anotherResource.method1(this);
        }
    }

    public static void main(String[] args) {
        final Resource resource1 = new Resource();
        final Resource resource2 = new Resource();

        // Thread 1
        new Thread(() -> {
            resource1.method1(resource2);
        }).start();

        // Thread 2
        new Thread(() -> {
            resource2.method1(resource1);
        }).start();
    }
}

Inter-Thread Communication Methods

// wait() — releases the lock and pauses the thread until notified
synchronized(obj) {
    obj.wait();
}

// notify() — wakes up one waiting thread
synchronized(obj) {
    obj.notify();
}

// notifyAll() — wakes up all waiting threads
synchronized(obj) {
    obj.notifyAll();
}

Inter-Thread Communication Flow

Thread A

wait()

Waiting State

notify() / notifyAll()

Runnable State

Execution Continues

Best Practices

  • Use consistent lock ordering to prevent circular waiting conditions.
  • Keep synchronized blocks small to reduce lock holding time.
  • Avoid nested locks to minimize the risk of deadlocks.
  • Prefer high-level concurrency utilities such as ReentrantLock, BlockingQueue, Semaphore, and ExecutorService.
  • Use notifyAll() carefully — only wake all threads when necessary.
  • Monitor multithreaded applications by analyzing thread dumps and lock usage regularly.

FAQ

1. What is a deadlock in Java?

A deadlock occurs when two or more threads wait indefinitely for locks held by each other, causing the application to stop progressing.

2. What are the methods used for inter-thread communication?

Java provides three methods from the Object class: wait(), notify(), and notifyAll().

3. What is the difference between wait() and sleep()?

wait() releases the object's lock and waits for a notification, while sleep() pauses execution for a specified time without releasing the lock.

Deadlock occurs when two or more threads wait indefinitely for locks held by each other.
Deadlocks arise from nested locks, circular waiting, and improper synchronization.
Inter-thread communication uses wait(), notify(), and notifyAll() from the Object class.
wait() releases the lock and places the thread in a waiting state.
notify() wakes one waiting thread; notifyAll() wakes all waiting threads.
wait(), notify(), and notifyAll() must always be called inside a synchronized block.
Use ReentrantLock or BlockingQueue for advanced deadlock-safe concurrency.

Where Java is used

Java in real-world development

Deadlock

A state where two or more threads block each other permanently by each waiting for a lock the other holds.

wait()

Causes the current thread to release its lock and enter the waiting state until another thread calls notify() or notifyAll().

notify()

Wakes up a single thread that is waiting on the same object's monitor lock.

notifyAll()

Wakes up all threads waiting on the object's monitor. The JVM scheduler decides which thread runs first.

Circular Waiting

A deadlock cause where Thread A waits for a lock held by Thread B, and Thread B waits for a lock held by Thread A.

ReentrantLock

A high-level lock with timeout support, offering a safer alternative to synchronized blocks for preventing deadlocks.

Prev: SynchronizationBack to hub