前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jstack分析多线程死锁,来吧老铁们

jstack分析多线程死锁,来吧老铁们

作者头像
公众号 IT老哥
修改2020-09-21 15:44:54
7830
修改2020-09-21 15:44:54
举报
文章被收录于专栏:用户7621540的专栏

本文源自 公-众-号 IT老哥 的分享

IT老哥,一个在大厂做高级Java开发的程序员,每天分享技术干货文章

前言

死锁:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

1、模拟死锁

代码语言:javascript
复制
public class DeadLockTest {
  public static void main(String[] args){
    A a = new A();
    B b = new B();
    
    // a和b互相引用
    a.next = b;
    b.next = a;
    
    // 启动a b两个线程
    new Thread(a,"aThread").start();
    new Thread(b,"bThread").start();
  }
}

class A extends T implements Runnable {
    T next;
    public synchronized void invoke() {
      System.out.println("当前线程:" + Thread.currentThread().getName()
              + " | 进入了" + this.getClass().getSimpleName() + " 获取到资源 | 准备调用:"
              + next.getClass().getSimpleName());
      try {
          Thread.sleep(1000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      next.invoke();
    }
    @Override
    public void run() {
      invoke();
    }
}

class B extends T implements Runnable {
    T next;
    public synchronized void invoke() {
        System.out.println("当前线程:" + Thread.currentThread().getName()
                + " | 进入了" + this.getClass().getSimpleName() + " 获取到资源 | 准备调用:"
                + next.getClass().getSimpleName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        next.invoke();
    }

    @Override
    public void run() {
        invoke();
    }
}

class T {
  public synchronized void invoke(){ }
}

上面的代码也很简单,就是A对象持有B对象的引用,B对象持有A对象的引用

在线程a进入到invoke方法时锁住了A对象,线程b也进入到invoke方法锁住了B对象。

线程a再调用B对象的invoke方法去试图锁住B对象时,发现B对象已经被锁住了,需要等待,同理b线程也是如此。

就导致了两个线程相互等待对方释放锁。有点绕,如果不明白,好好品下。

咱们运行下上面的代码,看下结果:

代码语言:javascript
复制
当前线程:aThread | 进入了A 获取到资源 | 准备调用:B
当前线程:bThread | 进入了B 获取到资源 | 准备调用:A

2、查找进程日志

我们使用jps查找进程,再用jstack dump线程日志信息

dump的时候忘记加磁盘标识,结果dump的文件到C:\Users\Administrator这个目录里面去了

3、分析

下面我们看看日志里面是怎么记录的,首先,我们全文搜索【deadlock】关键字,如下图:

上图展示了bThread和aThread发生了死锁,具体是哪块的代码还不清楚,咱们根据A对象0x000000078bb84c68继续往下搜索

现在咱们就很清楚死锁的代码所在了,剩下的就是优化代码了。

4、总结

一般来说,线程的日志是非常大,不可能一眼就能看出问题的所在,现在我们重点来说排查的思路:

首先就要找关键字,比如:

  • deadlock:表示有死锁。
  • Waiting on condition:等待某个资源或条件发生来唤醒自己。
  • Blocked:阻塞。
  • Waiting on monitor entry:在等待获取锁。

找到这些关键字,再找到具体的线程进行分析,最后根据线程死锁的执行的方法,去查看代码。

结束语

本篇到此把jstack命令介绍完了,下一篇将使用jmap的分析内存泄漏。

云服务器云硬盘数据库(包括MySQL、Redis、MongoDB、SQL Server),CDN流量包,短信流量包,cos资源包,消息队列ckafka,点播资源包,实时音视频套餐,网站管家(WAF),大禹BGP高防(包含高防包及高防IP),云解析SSL证书,手游安全MTP移动应用安全云直播等等。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT老哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本文源自 公-众-号 IT老哥 的分享
  • 前言
  • 1、模拟死锁
  • 2、查找进程日志
  • 3、分析
  • 4、总结
  • 结束语
相关产品与服务
SSL 证书
腾讯云 SSL 证书(SSL Certificates)为您提供 SSL 证书的申请、管理、部署等服务,为您提供一站式 HTTPS 解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档