class Resource
{
}
class MyThread1 extends Thread
{
Resource res1, res2;
MyThread1(Resource res1, Resource res2)
{
this.res1=res1;
this.res2=res2;
}
public void run()
{
synchronized(res1)
{
System.out.println("Thread 1 has allocated resource 1");
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
synchronized(res2)
{
System.out.println("Thread 1 has allocated resource 2");
}
}
}
}
class MyThread2 extends Thread
{
Resource res1, res2;
MyThread2(Resource res1, Resource res2)
{
this.res1=res1;
this.res2=res2;
}
public void run()
{
synchronized(res2)
{
System.out.println("Thread 2 has allocated resource 2");
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
synchronized(res1)
{
System.out.println("Thread 2 has allocated resource 1");
}
}
}
}
public class DeadlockDemo
{
public static void main(String[] args)
{
Resource res1=new Resource();
Resource res2=new Resource();
MyThread1 t1=new MyThread1(res1, res2);
t1.start();
MyThread2 t2=new MyThread2(res1, res2);
t2.start();
}
}
Thread 1 has allocated resource 1 Thread 2 has allocated resource 2 |
synchronized(res1)
{
synchronized(res2) // Avoid such nested locking if possible
{
// critical section
}
}
join()
with a timeout so the waiting thread doesn’t wait forever.
thread.join(1000); // wait for max 1 second
// Thread 1
synchronized(res1)
{
synchronized(res2)
{
// work with res1 and res2
}
}
// Thread 2 - use same order
synchronized(res1)
{
synchronized(res2)
{
// work with res1 and res2
}
}
res1
then res2
) and follow the same order everywhere.
class Resource
{
}
class MyThread1 extends Thread
{
Resource res1, res2;
MyThread1(Resource res1, Resource res2)
{
this.res1=res1;
this.res2=res2;
}
public void run()
{
synchronized(res1)
{
System.out.println("Thread 1 has allocated resource 1");
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
synchronized(res2)
{
System.out.println("Thread 1 has allocated resource 2");
}
}
}
}
class MyThread2 extends Thread
{
Resource res1, res2;
MyThread2(Resource res1, Resource res2)
{
this.res1=res1;
this.res2=res2;
}
public void run()
{
// FIX: Lock res1 first, then res2 (same as MyThread1)
synchronized(res1)
{
System.out.println("Thread 2 has allocated resource 1");
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println(e);
}
synchronized(res2)
{
System.out.println("Thread 2 has allocated resource 2");
}
}
}
}
public class DeadlockDemo
{
public static void main(String[] args)
{
Resource res1=new Resource();
Resource res2=new Resource();
MyThread1 t1=new MyThread1(res1, res2);
t1.start();
MyThread2 t2=new MyThread2(res1, res2);
t2.start();
}
}
Thread 1 has allocated resource 1 Thread 1 has allocated resource 2 Thread 2 has allocated resource 1 Thread 2 has allocated resource 2
ReentrantLock.tryLock(timeout)
so threads back off if the lock isn’t available, preventing deadlock.
if (lock.tryLock(1, TimeUnit.SECONDS))
{
try
{
// critical section
}
finally
{
lock.unlock();
}
}
else
{
System.out.println("Could not get lock, avoiding deadlock.");
}
Your feedback helps us grow! If there's anything we can fix or improve, please let us know.
We’re here to make our tutorials better based on your thoughts and suggestions.