I have two pieces of code . First one uses synchronized blocks and it causes a deadlock which is completely understandable.
In the second code i tried to recreate the same issue , but using Reentrant locks
this time. But the second code does not result in a deadlock in SOME CASES. Some cases there is a deadlock ,with nothing being printed in the console.
Can you pls explain why? Am i not using the Reentrant locks
correctly?
Code causing Deadlock
package com.practice.multithreading;
public class DeadlockYoutube {
public static void main(String[] args) {
final String resource1="Printer";
final String resource2="Scanner";
Runnable run1=()->{
synchronized (resource1) {
System.out.println(Thread.currentThread().getName()+" : locked-> "+resource1);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(resource2) {
System.err.println(Thread.currentThread().getName()+" : locked-> "+resource2);
}
}
};
Runnable run2=new Runnable(){
@Override
public void run() {
synchronized (resource2) {
System.out.println(Thread.currentThread().getName()+" : locked-> "+resource2);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(resource1) {
System.err.println(Thread.currentThread().getName()+" : locked-> "+resource1);
}
}
}
};
Thread thread1= new Thread(run1);
thread1.setName("Desktop");
Thread thread2=new Thread(run2);
thread2.setName("Laptop");
thread1.start();
thread2.start();
}
}
Same code with Reentrant Locks/not causing deadlocks
package com.practice.multithreading;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//not working as expected
public class DeadlockYoutubeReentrantLocks {
public static void main(String[] args) {
final String resource1 = "Printer";
final String resource2 = "Scanner";
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
Runnable run1 = () -> {
lock1.lock();
lock2.lock();
System.out.println(Thread.currentThread().getName() + " : locked-> " + resource1);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(Thread.currentThread().getName() + " : locked-> " + resource2);
lock1.unlock();
lock2.unlock();
};
Runnable run2 = new Runnable() {
@Override
public void run() {
lock2.lock();
lock1.lock();
System.out.println(Thread.currentThread().getName() + " : locked-> " + resource2);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(Thread.currentThread().getName() + " : locked-> " + resource1);
lock2.unlock();
lock1.unlock();
}
};
Thread thread1 = new Thread(run1);
thread1.setName("Desktop");
Thread thread2 = new Thread(run2);
thread2.setName("Laptop");
thread1.start();
thread2.start();
}
}
I tried reversing the order of the locks ..but the code executes fine sometimes and sometimes there is a deadlock and nothing is in the console.
Please explain the behavior.