下面代码模拟了多线程情境下,使用synchronized不当造成的死锁:
public class DeadlockTest {
private static Object lockA = new Object();
private static Object lockB = new Object();
public static void main(String[] agrs){
Thread t1 = new Thread(() -> {
synchronized(lockA) { // 获得lockA的锁
System.out.println("t1 getLockA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(lockB) { // 获得lockB的锁
System.out.println(" t1 getLockB");
} // 释放lockB的锁
} // 释放lockA的锁
System.out.println("t1 end");
});
Thread t2 = new Thread(() -> {
synchronized(lockB) { // 获得lockB的锁
System.out.println("t2 getLockB");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(lockA) { // 获得lockA的锁
System.out.println("t2 getLockA");
} // 释放lockA的锁
} // 释放lockB的锁
System.out.println("t2 end");
});
t1.start();
t2.start();
}
}
输出:
t1 getLockA
t2 getLockB
分析:
程序创建了两个线程:一个先尝试获得lockA的锁,进行耗时运算,然后尝试获取lockB的锁,进行其它运算。另一个线程则先尝试获得lockB的锁,进行耗时运算,然后尝试获取lockA的锁,进行其余处理。
两个线程同时运行的话,就会造成耗时任务结束时,都在等待对方的锁释放,而谁都拿不到锁,就产生死锁。所以只打印出了上面的结果,如果不强制结束程序的话,会一直无限等待下去。
另外,程序中模拟耗时运算用的是等待1s,如果此例中没有耗时运算(去掉Thread.sleep)的话,死锁就可能发生,也可能不会发生了。