您当前的位置: 首页 >  Java

java持续实践

暂无认证

  • 1浏览

    0关注

    746博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java多线程 定位死锁--jstack

java持续实践 发布时间:2020-09-11 08:10:50 ,浏览量:1

文章目录
      • jstack定位死锁
      • 两个线程死锁分析
      • 多个线程死锁分析

jstack定位死锁

死锁发生的时候, 控制台什么也不打印, 无法进行排查. 这个时候就需要借助工具来进行定位死锁了. 工具之一就是jdk自带的命令jstack 在jdk的bin 目录中,可以看到是有jstack.exe这个应用程序的,配置好了jdk的环境变量后,那么就可以直接用jstack来分析死锁了.

两个线程死锁分析

首先分析两个线程死锁的情况 运行之前的章节中, 两个线程必然发生死锁的代码demo

package com.thread.deadlock;

/**
 * 类名称:MustDeadLock
 * 类描述:   必定发生死锁的情况
 *
 * @author: https://javaweixin6.blog.csdn.net/
 * 创建时间:2020/9/8 7:55
 * Version 1.0
 */
public class MustDeadLock implements Runnable {
    //标记位, 不同的线程根据标记位执行不同的代码
    int flag = 1 ;

    //两把锁
    static Object o1 = new Object();
    static Object o2 = new Object();

    public static void main(String[] args) {
        MustDeadLock r1 = new MustDeadLock();
        MustDeadLock r2 = new MustDeadLock();
        //给不同的线程, 设置不同的标记位
        r1.flag=1;
        r2.flag=2;

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        //打印出标记位
        System.out.println("flag = "+flag);
        if (flag == 1) {
            synchronized (o1) {
                try {
                    //线程1持有锁o1, 并且等待500ms ,让线程2执行
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //线程1尝试去获取锁o2
                synchronized (o2) {
                    System.out.println("线程1成功拿到两把锁");
                }

            }
        }

        if (flag == 2) {

            synchronized (o2) {

                try {
                    //持有锁o2, 并且等待500ms ,让线程1执行
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //线程2尝试去获取锁o1
                synchronized (o1) {
                    System.out.println("线程2成功拿到两把锁");
                }
            }
        }
    }
}

运行程序 , 可以看到控制台打印了1 和2之后, 再也没打印出东西了, 也没报错, 但是可以看到红色的按钮是亮着的,程序进入了阻塞的状态. 首先用jps 找出当前运行程序的PID, 可以看到我们自己运行的类MustDeadLock的PID为10052 输入jstack 10052 可以看到打印出来了线程间死锁的信息. 线程1持有0x000000076e471818这把锁, 需要0x000000076e471808这把锁. 线程0持有0x000000076e471808这把锁,需要0x000000076e471818这把锁.因此就造成了死锁. 把打印信息拖到最下面, 也可以看到 提示发现了一个死锁Found 1 deadlock

多个线程死锁分析

运行如下的多人转账的代码案例

package com.thread.deadlock;

import java.util.Random;

/**
 * 类名称:MultiTransferMoney
 * 类描述: 多人转账发生死锁demo
 *
 * @author: https://javaweixin6.blog.csdn.net/
 * 创建时间:2020/9/9 7:13
 * Version 1.0
 */
public class MultiTransferMoney {

    //账户的总数量
    private static final int NUM_ACCOUNTS = 500;

    //每个账户初始的余额
    private static final int NUM_MONEY = 1000;
    private static final int NUM_ITERATIONS = 1000000;
    private static final int NUM_THREADS = 20;

    public static void main(String[] args) {
        Random random = new Random();

        //定义转账的账户数组
        TransferMoney.Account[] accounts = new TransferMoney.Account[NUM_ACCOUNTS];

        for (int i = 0; i             
关注
打赏
1658054974
查看更多评论
0.0430s