什么是死锁?
死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的互相等待的现象,若无外力干涉则都无法继续推进。如果系统资源充足,线程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。
像上面这种,线程A持有锁A并尝试获取锁B,线程B持有锁B并尝试获取锁A,造成死锁。
产生死锁的主要原因:
- 系统资源不足
- 进程运行推进的顺序不合适
- 资源分配不当
1、举例死锁
class MyLockData implements Runnable{
private String mLockA;
private String mLockB;
public MyLockData(String mLockA, String mLockB) {
this.mLockA = mLockA;
this.mLockB = mLockB;
}
@Override
public void run() {
synchronized (mLockA){
System.out.println(Thread.currentThread().getName() + " 持有:"+mLockA+" 并申请锁:"+mLockB);
try {
TimeUnit.SECONDS.sleep(2L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mLockB){
System.out.println(Thread.currentThread().getName() + " 持有:"+mLockB+" 并申请锁:"+mLockA);
}
}
}
}
public class MyLockDemo {
public static void main(String[] args) {
final MyLockData data = new MyLockData("α锁","β锁");
final MyLockData data2 = new MyLockData("β锁","α锁");
new Thread(new Runnable() {
@Override
public void run() {
data.run();
}
},"线程A").start();
new Thread(new Runnable() {
@Override
public void run() {
data2.run();
}
},"线程B").start();
}
}
--------------------
线程A 持有:α锁 并申请锁:β锁
线程B 持有:β锁 并申请锁:α锁
2、证明死锁
windows下的进程查看命令:
- jps -l:可以查看有问题的类及其进程编号;
- jstack xxxx:xxxx就是上一步查询出来的进程编号,可以查看该类下的具体问题所在。
2.1、运行程序,进入“死锁”状态;
2.2、在控制台 Terminal 栏输入命令:jps -l,查看哪些类有问题,
扫描二维码关注公众号,回复:
11570154 查看本文章
2.3、接着输入命令:jstack -7424,查看这个类到底出了什么问题
Found 1 deadlock. 原因,红框部分一目了然。
3.解决死锁
根据上一步找到死锁的原因,找到相关代码进行整理优化,重启服务器。