Sunday 24 September 2017

DeadLock in Multithreading in Java


Deadlock is a situation  where one thread1(t1) is waiting for the release of a lock(say str1) acquired by another thread t2 and this thread is waiting for the release of the lock (say str2) acquired by  first thread t1.



 This condition creates a never ending process of release of lock and no threads ever able to acquire the lock and programme hang in this state.

Deadlock is tricky situation and most likely not able to reproduce in many condition,  but should be handle  with full care.

I will try to demonstrate couple of scenarios where  deadlock doesn't occur but probable code of creating a deadlock and another scenario where deadlock occurs for sure and application remain in hanged state.

Demo 1 : Situation likely to be a deadlock but works well and doesn't hang the application.

public class MultiThreading {
String s1 = "John";
String s2 = "Cena";
Thread t1 = new Thread(() -> {
synchronized (s1) {
synchronized (s2) {
System.out.println(s1 + " " + s2);
}
}
});
Thread t2 = new Thread(() -> {
synchronized (s2) {
synchronized (s1) {
System.out.println(s2 + " " + s1);
}
}
});

public static void main(String[] args) {
MultiThreading mt = new MultiThreading();
mt.t1.start();
mt.t2.start();
}

}

Output : 

John Cena
Cena John


Demo2 : Deadlock occurs and application gets in the hanged state with the addition of a while loop in the above code.

public class MultiThreading {
String s1 = "John";
String s2 = "Cena";
Thread t1 = new Thread(() -> {
while (true) {  /// note that addition of this loop
synchronized (s1) {
synchronized (s2) {
System.out.println(s1 + " " + s2);
}
}
}
});
Thread t2 = new Thread(() -> {
while (true) {  /// note that addition of this loop
synchronized (s2) {
synchronized (s1) {
System.out.println(s2 + " " + s1);
}
}
}
});

public static void main(String[] args) {
MultiThreading mt = new MultiThreading();
mt.t1.start();
mt.t2.start();
}
}

Ouptut :  [prints following then application gets hanged]

John Cena
John Cena
John Cena
John Cena
John Cena
John Cena


Most likely deadlock to be occurred in the places where inside of some loop multiple threads are accessing common resources which is common among the thread.

How to avoid deadlock ?

Answer : Mutex is the saviour in this kind of situation. Mutex is a semaphore with a permit count 1 . It allows one thread at a time to consume the common resource and other thread need a permit from the semaphore before using the resource. This exclusion of the common resource from the multi thread allows the updates on the value of the common resource safe and doesn't corrupt the data and make thread safe. 

If run the same above code of deadlock using a mutex , then it goes well without hanging the application.

public class MultiThreading {
String s1 = "John";
String s2 = "Cena";
Semaphore semaphore = new Semaphore(1);
Thread t1 = new Thread(() -> {
while (true) {
try{
semaphore.acquire();
synchronized (s1) {
synchronized (s2) {
System.out.println(s1 + " " + s2);
}
}
}catch(Exception e){
} finally {
semaphore.release();
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
try{
semaphore.acquire();
synchronized (s2) {
synchronized (s1) {
System.out.println(s2 + " " + s1);
}
}
}catch(Exception e){
} finally {
semaphore.release();
}
}
});

public static void main(String[] args) {
MultiThreading mt = new MultiThreading();
mt.t1.start();
mt.t2.start();
}
}

Output : [without hanging :) and without deadlock :) ]

Cena John
Cena John
Cena John
Cena John
Cena John
Cena John
Cena John
Cena John
Cena John 

Enjoy the coding and multithreading!!!!