死锁
什么是死锁
死锁就是锁对象的循环等待问题
public static void main(String[] args) {
Object lock1 = new Object();
Object lock2 = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock1) {
System.out.println("我想看t2表演个才艺之后再开始学习~");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lock2) {
System.out.println("舒服了,我现在开始学习了");
}
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("等t1学习结束之后,我再给他来个才艺展示~");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lock1) {
System.out.println("可以, 我给你展示一下我的才艺~");
}
}
}, "t2");
t1.start();
t2.start();
}
// 执行结果
等t1学习结束之后,我再给他来个才艺展示~
我想看t2表演个才艺之后再开始学习~
t1线程在等lock2释放锁,t2线程在等lock1释放锁,结果谁都拿不到锁,这就是死锁
我们通过jconsole命令查看以下t1和t2线程的状态(点击“检测死锁”):
t1线程的状态:此时t1想要获取的锁正被t2线程持有

t2线程的状态:此时t2想要获取的锁正被t2线程持有:

有个非常著名的“哲学家进餐问题” - 就是一个死锁问题,锁的循环等待问题
死锁的避免
死锁产生的四个必要条件:
- 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
- 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
- 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
- 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样 就形成了一个等待环路
当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。
但是前面三个条件就是互斥锁的概念,没法破坏,其中最容易破坏的就是 “循环等待”,即不让多个线程获取资源你不要成环即可
public static void main(String[] args) {
Object lock1 = new Object();
Object lock2 = new Object();
Thread t1 = new Thread(() -> {
synchronized (lock2) {
System.out.println("我现在开始学习了");
synchronized (lock1) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("学习结束! 我想看t2表演~");
}
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (lock2) {
System.out.println("等t1学习结束之后,我再给他来个才艺展示~");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (lock1) {
System.out.println("可以, 我给你展示一下我的才艺~");
}
}
}, "t2");
t1.start();
t2.start();
}
// 执行结果
我现在开始学习了
学习结束! 我想看t2表演~
等t1学习结束之后,我再给他来个才艺展示~
可以, 我给你展示一下我的才艺~
版权声明:本文为m0_61925333原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。