线程死锁的原因:当两个或多个线程正在等待对方占有的锁,死锁就会发生
死锁会导致两个线程无法继续运行,被永远挂起。
简单的死锁例子
创建两个互相等待对方释放锁的线程
public class DeadLock1 implements Runnable {
private Object o1, o2;
public DeadLock1(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
@Override
public void run() {
fun();
}
public void fun() {
//获取o1的monitor
synchronized (o1) {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取o2的monitor
synchronized (o2) {
}
}
}
}
public class DeadLock2 implements Runnable {
private Object o1, o2;
public DeadLock2(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
@Override
public void run() {
fun();
}
public void fun() {
//获取o2的monitor
synchronized (o2) {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取o1的monitor
synchronized (o1) {
}
}
}
}
创建测试类
public class TestDeadLock {
public static void main(String[] args) {
Object lockObj1 = new Object();
Object lockObj2 = new Object();
//分别启动两个线程
Thread thread1 = new Thread(new DeadLock1(lockObj1, lockObj2));
thread1.start();
Thread thread2 = new Thread(new DeadLock2(lockObj1, lockObj2));
thread2.start();
}
}
运行并打印堆栈信息:
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x0000000054a4d6b8 (object 0x00000000eb540e20, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x0000000054a4c218 (object 0x00000000eb540e30, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at zj.test.deadlock.DeadLock2.fun(DeadLock2.java:33)
- waiting to lock <0x00000000eb540e20> (a java.lang.Object)
- locked <0x00000000eb540e30> (a java.lang.Object)
at zj.test.deadlock.DeadLock2.run(DeadLock2.java:19)
at java.lang.Thread.run(Thread.java:745)
"Thread-0":
at zj.test.deadlock.DeadLock1.fun(DeadLock1.java:33)
- waiting to lock <0x00000000eb540e30> (a java.lang.Object)
- locked <0x00000000eb540e20> (a java.lang.Object)
at zj.test.deadlock.DeadLock1.run(DeadLock1.java:19)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.
线程0想要lock <0x00000000eb540e30>
线程1想要lock <0x00000000eb540e20>
双方都在等待对方释放锁
对于真正的死锁而言,虚拟机从锁的持有和请求情况就能判断出来,因此打印堆栈时虚拟机会自动给出死锁的提示
许多人把系统无响应的问题统称为死锁,这种称为是不恰当的
真正意义上的死锁是由于代码引入的错误而导致的死锁
要想从死锁中恢复临时也是唯一的规避办法是将系统重启,然后赶快去修改导致这个死锁的BUG
能否及时发现死锁,依赖于你的运气和你准备的测试用例的有效性
tips:死锁的两个或多个线程是不消耗CPU的