死锁及其解决

1、死锁概述

锁在开发中会经常用到,使用起来也是非常简单。但是如果业务比较复杂,使用不当的话,会出现死锁,
这是非常严重的问题。下面代码会造成死锁。

public class DeadLock {
    private final static String A = "A";
    private final static String B = "B";

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (A){
                try{
                    Thread.sleep(1000l);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (B){
                    System.out.println("A");
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (B){
                synchronized (A){
                    System.out.println("B");
                }
            }
        });

        t1.start();
        t2.start();
    }
}

在一些复杂的场景下,可能会出现上述情况。
究其原因,t1因为某些情况没有释放掉A锁,t2在获取B锁的情况下去拿A锁,此时A锁被占用拿不到,t1在释放掉A锁的情况下,去拿B锁,此时B锁又被t2占有。导致t1,t2相互占用对方待获取的锁,且又互不相让,形成死锁。

2、排查死锁问题

windows下(测试一下)
1、打开资源管理器,查看pid;或者cmd,使用jps命令。
2、使用jstack命令,dump日志
D:\Java\jdk1.8.0_211\bin>jstack 17260 > D:/mylock.txt
3、查看日志,搜索deadlock,发现如下:
在这里插入图片描述
4、根据实际情况解决问题

linux下:
1、使用jps找到java进程pid
2、使用jstack命令找到该进程下线程情况
jstack pid
3、找到跟我们自己代码相关的线程
定位到waiting的线程,或者deadlock的线程

一般情下,可以先找到最消耗cpu的进程,再通过jstack定位到问题代码。
1、先找到Java进程id
ps -ef | grep java
2、找出该进程内最耗费CPU的线程,可以使用top -Hp pid
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。
3、将最费时的线程转化为16进制
printf “%x\n” 21742,得到21742的十六进制值为54ee
4、使用jstack打印堆栈信息
jstack 21711 | grep 54ee

死锁的产生条件

(1) 互斥条件:一个资源每次只能被一个进程(线程)使用。
(2) 请求与保持条件:一个进程(线程)因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件 : 此进程(线程)已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件 : 多个进程(线程)之间形成一种头尾相接的循环等待资源关系。

如何避免死锁

死锁的产生主要是因为相互占用对方想要获取的资源,导致相互等待。一般的解决方式如下:
1、·避免一个线程同时获取多个锁。
2、·避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
3、 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
4、·对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值