public class DeadlockDemo2 {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadDemo1 demo1 = new ThreadDemo1();
ThreadDemo2 demo2 = new ThreadDemo2();
demo1.start();
demo2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
In above program, both Threads are sleeping for 10 milliseconds. So once the time expires, demo1 can acquire lock on lock2 and demo2 on lock1. But It does not happen so. They go under deadlock.
Can somebody explain the reason?
Thanks in advance.
We'll ignore the design issues here and assume you're just trying to understand threading with a toy example.
The problem is your lock scoping. Let's list out the order of operations here:
In
ThreadDemo1
:Lock1
Lock2
Lock2
Lock1
Similarly, in
ThreadDemo2
:Lock2
Lock1
Lock1
Lock2
As you can see from the order of operations here, both of your
ThreadDemo
classes attempt to acquire the other lock before freeing their initial lock. This basically guarantees deadlock as they will be stuck forever waiting for the other to release their initial lock.What you actually wanted to happen was this in
ThreadDemo1
:Lock1
Lock1
Lock2
Lock2
And this in
ThreadDemo2
:Lock2
Lock2
Lock1
Lock1
To do this, simply change this:
To this:
And make the same change in your
ThreadDemo2
class