How to create a deadlock in Java
This article shows how to create a deadlock in Java.
A deadlock occurs when two threads each hold a lock that the other thread is waiting for. Neither of them can proceed without acquiring the lock held by the other thereby creating a deadlock.
To study and analyse a deadlock you should be able to create one. This article shows you how to do it.
First, we define two locks. Then, we create two threads that acquire both the locks one by one but in different orders. Thread A acquires lock A first then waits for sometime while Thread B acquires lock B. Then, thread A tries to acquire lock B and vice versa. And you have a deadlock created!
Let me show you the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
package com.wilddiary.concurrency; public class DeadLockTest { // define the locks private static Object lockA = new Object(); private static Object lockB = new Object(); public static void main(String[] args) throws InterruptedException { System.out.println("Creating a deadlock situation :) \n"); Thread threadA = new Thread(new WorkerA(), "A"); Thread threadB = new Thread(new WorkerB(), "B"); threadA.start(); threadB.start(); } static class WorkerA implements Runnable{ @Override public void run() { // acquire lock A first synchronized (lockA) { System.out.println("Worker A acquired lock on lock A"); // sleep to let other thread acquire lock B try { Thread.sleep(100); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("Worker A waiting to acquire lock on lock B. If it can not then it is a deadlock!"); // now, try acquiring lock B. It can't. synchronized (lockB) { // won't get here System.out.println("Worker A acquired lock on lock B"); while(true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } // synchornized block on lock B ends } // synchornized block on lock A ends } // run() method ends } // class WorkerA ends static class WorkerB implements Runnable{ @Override public void run() { synchronized (lockB) { System.out.println("Worker B acquired lock on lock B"); // sleep to let other thread acquire lock A try { Thread.sleep(100); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("Worker B waiting to acquire lock on lock A. If it can not then it is a deadlock!"); // now, try acquiring lock A. It can't. synchronized (lockA) { // won't get here System.out.println("Worker B acquired lock on lock A"); while(true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } } |
Output
1 2 3 4 5 6 7 |
Creating a deadlock situation :) Worker A acquired lock on lock A Worker B acquired lock on lock B Worker A waiting to acquire lock on lock B. If it can not then it is a deadlock! Worker B waiting to acquire lock on lock A. If it can not then it is a deadlock! |
ThreadSafe is a static analysis tool that automatically finds Java concurrency defects. It finds this one, of course, but it also quickly finds much more complicated deadlocks and race conditions in million-line codebases. See http://www.contemplateltd.com/threadsafe for more information, and to get a free two-week trial.
(Disclosure: ThreadSafe is a commercial tool, and I’m co-founder of Contemplate, the company that produces it.)