多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
如图:两个或以上的进程因为争夺资源而造成互相等待资源的现象称为死锁。
1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
注意
:当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。
可理解背下来,大厂面试可考,死锁的简单案例
public class DeadLock {
//创建两个对象
static Object a = new Object();
static Object b = new Object();
public static void main(String[] args) {
new Thread(()->{
synchronized (a) {
System.out.println(Thread.currentThread().getName()+" 持有锁a,试图获取锁b");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {
System.out.println(Thread.currentThread().getName()+" 获取锁b");
}
}
},"A").start();
new Thread(()->{
synchronized (b) {
System.out.println(Thread.currentThread().getName()+" 持有锁b,试图获取锁a");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a) {
System.out.println(Thread.currentThread().getName()+" 获取锁a");
}
}
},"B").start();
}
}
jps和jstack工具位于JDK文件夹的bin目录下
运行命令jps -l
或者jps可以查看所有Java
进程的PID
区别:
jps -l
:显示类的全限定名称jps
:显示类名
由于我们创建的类名为DeadLock
,我们可以直接根据类名来判断
此时,可以看到DeadLock类的PID为20812
然后使用堆栈跟踪工具jstack+进程号PID来查看结果
jstack [进程id] > [导出文件存储的位置]
Java stack information for the threads listed above:
===================================================
"A":
at com.wk.concurrency.demo.DeadLock.lambda$deadLock$1(DeadLock.java:27)
- waiting to lock <0x00000007412cd8d0> (a java.lang.String)
- locked <0x00000007412cd900> (a java.lang.String)
at com.wk.concurrency.demo.DeadLock$$Lambda$2/804581391.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
"B":
at com.wk.concurrency.demo.DeadLock.lambda$deadLock$0(DeadLock.java:20)
- waiting to lock <0x00000007412cd900> (a java.lang.String)
- locked <0x00000007412cd8d0> (a java.lang.String)
at com.wk.concurrency.demo.DeadLock$$Lambda$1/6738746.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.
分析结果
任何线程进入同步代码块、同步方法之前,必须获得同步监视器的锁定,那么何时会释放这个锁定呢?在程序中,是无法显式释放对同步监视器的锁的,而会在如下几个情况下释放锁。
1.尽量避免使用多个锁(如果有可能的话)。
2.规范的使用多个锁,并设计好锁的获取顺序。
3.随用随放。即是,手里有锁,如果还要获得别的锁,必须释放全部资源才能各取所需。
4.规范好循环等待条件。比如,使用超时循环等待,提高程序可控性
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_31762741/article/details/123274086
内容来源于网络,如有侵权,请联系作者删除!