- 死锁的由来
- 死锁产生的条件
- demo演示死锁
- 死锁出现原因图谱
- 分析死锁
- 1、jps -l 查看程序执行的进程
- 2、通过 jstack -l pid 查看堆栈内存
在实际开发中,并发开发中难免会碰见死锁的问题。
出现死锁问题后,程序中的现象为:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
死锁产生的条件- 1、互斥使用。
当资源被一个线程使用(占有)时,别的线程不能使用。 - 2、不可抢占。
资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。 - 3、请求和保持。
当资源请求者在请求其他的资源的同时保持对原有资源的占有。 - 4、循环等待。
存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
编写一个demo案例,满足上述死锁4要素,模拟死锁。
package lock;
import java.util.concurrent.TimeUnit;
public class DLTest {
public static void main(String[] args) {
String lockA = "lockA";
String lockB = "lockB";
// 操作的是两个不同的对象
// 线程1:lockA lockB
new Thread(new MyLock(lockA,lockB),"t1").start();
// 线程2:lockB lockA
new Thread(new MyLock(lockB,lockA),"t1").start();
}
}
// 给定一个线程
class MyLock implements Runnable{
// 对资源加锁,这里的资源只是一个变量
private String lock1;
private String lock2;
public MyLock(String lock1, String lock2) {
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
synchronized (lock1){
System.out.println("当前线程1:"+ Thread.currentThread().getName()+" 持有锁 "+lock1+" ==>"+lock2);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2){
System.out.println("当前线程2:"+ Thread.currentThread().getName()+" 持有锁 "+lock2+" ==>"+lock1);
}
}
}
}
程序执行后,控制台日志信息如下所示:
在本地进行代码运行测试,从控制台的日志中就能知道是否发生了死锁现象。但是如果部署到了服务器上,通过程序执行的log 日志并不能更为直观的知道是否发生了死锁问题。
此时,可以通过jdk提供的命令进行相应的信息分析。
1、jps -l 查看程序执行的进程 2、通过 jstack -l pid 查看堆栈内存jstack -l 23912
通过堆栈内存数据信息,很直观的能发现是代码的哪处位置出现的什么问题。



