Background
This is one of the very basic Java multithreading question - to write a simple java program to demonstrate a deadlock. So in this post I will provide code to demonstrate that -
Java code to create deadlock between two threads
Code is as follows -
/** * * @author athakur * Simple deadlock program */ public class Deadlock { public static void main(String args[]) { final Object resourceOne = "res1"; final Object resourceTwo = "res2"; new Thread(new Runnable() { @Override public void run() { synchronized(resourceOne) { System.out.println(Thread.currentThread().getName() + " accquired resource 1"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } synchronized(resourceTwo) { System.out.println(Thread.currentThread().getName() + " accquired resource 2"); } } } }).start(); new Thread(new Runnable() { @Override public void run() { synchronized(resourceTwo) { try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " accquired resource 2"); synchronized(resourceOne) { System.out.println(Thread.currentThread().getName() + " accquired resource 1"); } } } }).start(); } }
Copy above code in Deadloc.java file, compile and run it. You should see following output in console -
Thread-0 accquired resource 1
Thread-1 accquired resource 2
Thread-1 accquired resource 2
And the program should hang.
Explanation
Thread 1 acquires lock over resource 1 and goes to sleep for 2 seconds. After sleep it would try to acquire lock on resource 2. When thread 1 was sleeping, thread 2 acquired lock over resource 2 and went to sleep for 2 seconds. After 2 seconds thread 2 would try to acquired lock on resource 1. Now it does not matter which thread wakes up. It will not be able to get lock on inner resource as other thread has acquired it and waiting for other to release. This will led to deadlock.
How to resolve this deadlock?
You can use Reentrant locks introduced in Java 1.5 to check if lock is available before locking it or you can do a timed lock (If lock is not available in x time move on).
Another way to resolve this is to always have a fixed order to acquire lock. So both T1 and T2 threads will always lock resource 1 before trying to acquire lock on resource 2. This breaks the cycle that can lead to deadlock.
There is more more stupid way to prevent deadlock. When you are spawning new threads from main thread call join from main thread on all new threads before calling start() on next thread. Stupid? I know. It is same as single threaded application as you are executing threads sequentially.
Couple of tips that may come handy -
- don't use multiple threads (like Swing does, for example, by mandating that everything is done in the EDT)
- don't hold several locks at once. If you do, always acquire the locks in the same order
- don't execute foreign code while holding a lock
- use interruptible locks
No comments:
Post a Comment