死锁是并发中常见的问题,在业务逻辑复杂,锁较多时发生死锁饿的概率极大。死锁产生的主要原因在于线程之间“死等”对方手里的锁。
案例:
package com.yc.uc.test;
class Resouces{
private String lockA;
private String lockB;
public Resouces(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
}
public void test() throws InterruptedException {
synchronized (lockA){
System.out.println(Thread.currentThread().getName()+"已经获取"+lockA+"尝试获取"+lockB);
Thread.sleep(2000);
synchronized (lockB){
System.out.println("两个锁都已获取!");
}
}
}
}
/**
* @Author Allen
* @Date 2021/3/8 10:35 上午
* @Version 1.0
*/
public class DeadLockDemo {
public static void main(String[] args) {
String lock1 = "lock1";
String lock2 = "lock2";
new Thread(()->{
try {
new Resouces(lock1,lock2).test();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
new Resouces(lock2,lock1).test();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
运行结果:
Thread-0已经获取lock1尝试获取lock2
Thread-1已经获取lock2尝试获取lock1
//阻塞,并未结束
死锁产生以后,线程阻塞,极为隐蔽,在一般情况下较难发现。
分析方法:
终端指令:jps(java+ps)在终端查看进程号
(base) mac@lzydeMacBook-Pro /etc % jps
1744 Launcher
2144 Jps
//找到可能产生死锁的 全类名
1745 DeadLockDemo
329
559
终端指令:jstack 1745
(base) mac@lzydeMacBook-Pro /etc % jstack 1745
2021-03-08 10:57:00
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):
......
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.yc.uc.test.Resouces.test(DeadLockDemo.java:16)
- waiting to lock <0x0000000795aa1468> (a java.lang.String)
- locked <0x0000000795aa14a0> (a java.lang.String)
at com.yc.uc.test.DeadLockDemo.lambda$main$1(DeadLockDemo.java:42)
at com.yc.uc.test.DeadLockDemo$$Lambda$2/739498517.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at com.yc.uc.test.Resouces.test(DeadLockDemo.java:16)
- waiting to lock <0x0000000795aa14a0> (a java.lang.String)
- locked <0x0000000795aa1468> (a java.lang.String)
at com.yc.uc.test.DeadLockDemo.lambda$main$0(DeadLockDemo.java:34)
at com.yc.uc.test.DeadLockDemo$$Lambda$1/1552787810.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
可以查看到产生死锁的具体位置和对应的锁