I would like to explain threading deadlocks to newbies. I have seen many examples for deadlocks in the past, some using code and some using illustrations (like the famous 4
CountDownLatch countDownLatch = new CountDownLatch(1);
ExecutorService executorService = ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(() -> {
Future<?> future = executorService.submit(() -> {
System.out.println("generated task");
});
countDownLatch.countDown();
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
countDownLatch.await();
executorService.shutdown();
Here's a code example from the computer science department of a university in Taiwan showing a simple java example with resource locking. That's very "real-life" relevant to me. Code below:
/**
* Adapted from The Java Tutorial
* Second Edition by Campione, M. and
* Walrath, K.Addison-Wesley 1998
*/
/**
* This is a demonstration of how NOT to write multi-threaded programs.
* It is a program that purposely causes deadlock between two threads that
* are both trying to acquire locks for the same two resources.
* To avoid this sort of deadlock when locking multiple resources, all threads
* should always acquire their locks in the same order.
**/
public class Deadlock {
public static void main(String[] args){
//These are the two resource objects
//we'll try to get locks for
final Object resource1 = "resource1";
final Object resource2 = "resource2";
//Here's the first thread.
//It tries to lock resource1 then resource2
Thread t1 = new Thread() {
public void run() {
//Lock resource 1
synchronized(resource1){
System.out.println("Thread 1: locked resource 1");
//Pause for a bit, simulating some file I/O or
//something. Basically, we just want to give the
//other thread a chance to run. Threads and deadlock
//are asynchronous things, but we're trying to force
//deadlock to happen here...
try{
Thread.sleep(50);
} catch (InterruptedException e) {}
//Now wait 'till we can get a lock on resource 2
synchronized(resource2){
System.out.println("Thread 1: locked resource 2");
}
}
}
};
//Here's the second thread.
//It tries to lock resource2 then resource1
Thread t2 = new Thread(){
public void run(){
//This thread locks resource 2 right away
synchronized(resource2){
System.out.println("Thread 2: locked resource 2");
//Then it pauses, for the same reason as the first
//thread does
try{
Thread.sleep(50);
} catch (InterruptedException e){}
//Then it tries to lock resource1.
//But wait! Thread 1 locked resource1, and
//won't release it till it gets a lock on resource2.
//This thread holds the lock on resource2, and won't
//release it till it gets resource1.
//We're at an impasse. Neither thread can run,
//and the program freezes up.
synchronized(resource1){
System.out.println("Thread 2: locked resource 1");
}
}
}
};
//Start the two threads.
//If all goes as planned, deadlock will occur,
//and the program will never exit.
t1.start();
t2.start();
}
}
If method1() and method2() both will be called by two or many threads, there is a good chance of deadlock because if thread 1 acquires lock on String object while executing method1() and thread 2 acquires lock on Integer object while executing method2() both will be waiting for each other to release lock on Integer and String to proceed further, which will never happen.
public void method1() {
synchronized (String.class) {
System.out.println("Acquired lock on String.class object");
synchronized (Integer.class) {
System.out.println("Acquired lock on Integer.class object");
}
}
}
public void method2() {
synchronized (Integer.class) {
System.out.println("Acquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Acquired lock on String.class object");
}
}
}
public class DeadLock {
public static void main(String[] args) throws InterruptedException {
Thread mainThread = Thread.currentThread();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
mainThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread1.join();
}
}
public class DeadlockProg {
/**
* @Gowtham Chitimi Reddy IIT(BHU);
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final Object ob1 = new Object();
final Object ob2 = new Object();
Thread t1 = new Thread(){
public void run(){
synchronized(ob1){
try{
Thread.sleep(100);
}
catch(InterruptedException e){
System.out.println("Error catched");
}
synchronized(ob2){
}
}
}
};
Thread t2 = new Thread(){
public void run(){
synchronized(ob2){
try{
Thread.sleep(100);
}
catch(InterruptedException e){
System.out.println("Error catched");
}
synchronized(ob1){
}
}
}
};
t1.start();
t2.start();
}
}
I recently realized that the fights between couples are nothing but a deadlock.. where usually one of the process has to crash to resolve it, of course it's the lesser priority one(Boy ;)).
Here's the analogy...
Process1: Girl(G) Process2: Boy(B)
Resource1: Sorry Resource2: Accepting own mistake
Necessary Conditions:
1. Mutual Exclusion: Only one of G or B can say sorry or accept own Mistake at a time.
2. Hold and Wait: At a time, one is holding Sorry and other Accepting own mistake, one is waiting for Accepting own mistake to release sorry, and other is waiting for sorry to release accepting own mistake.
3. No preemption: Not even God can force B or G to release Sorry or Accepting own mistake. And voluntarily? Are you kidding me??
4. Circular Wait: Again, the one holding sorry waits for other to accept own mistakes, and one holding accept own mistakes want other to say sorry first. So it's circular.
So deadlocks occur when all these conditions are in effect at the same time, and that's always the case in a couple fight ;)
Source: http://www.quora.com/Saurabh-Pandey-3/Posts/Never-ending-couple-fights-a-deadlock