Java multi-thread positioning deadlock--jstack

Jstack positioning deadlock

When a deadlock occurs, the console does not print anything and cannot be checked. At this time, you need to use tools to locate the deadlock.
One of the tools is the jdk's own command jstack
in the jdk bin directory, you can see that it is With jstack.exethis application, after configuring the jdk environment variables, you can directly use jstack to analyze the deadlock.

Two thread deadlock analysis

First analyze the deadlock situation of the two threads. In the
previous chapters, the two threads will inevitably deadlock the code 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成功拿到两把锁");
                }
            }
        }
    }
}

Run the program, you can see that after the console has printed 1 and 2, nothing is printed anymore, and no error is reported, but you can see that the red button is on and the program has entered a blocked state.

First use jps to find PID of the currently running program, you can see the PID class MustDeadLock our own run for the 10052

input jstack 10052can see the information printed deadlock between threads.
thread 1 holds 0x000000076e471818the lock, you need 0x000000076e471808the lock.
thread holding 0 There is 0x000000076e471808this lock, and this lock is needed 0x000000076e471818. Therefore, a deadlock is caused.

Drag the printed information to the bottom, and you can also see the prompt that a deadlock was foundFound 1 deadlock

Multiple thread deadlock analysis

Run the following code example for multi-person transfer

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 < accounts.length; i++) {
    
    
            //给每个账户数组中的元素定初始值
            accounts[i] = new TransferMoney.Account(NUM_MONEY);
        }

        class TransferThread extends Thread {
    
    

            @Override
            public void run() {
    
    
                //每一个线程都进行随机的转账

                for (int i = 0; i < NUM_ITERATIONS; i++) {
    
    
                    //随机获取转账方索引
                    int fromAccount = random.nextInt(NUM_ACCOUNTS);
                    //随机的获取收款方
                    int toAccount = random.nextInt(NUM_ACCOUNTS);
                    //随机获取转账金额
                    int amount = random.nextInt(NUM_MONEY);

                    //执行转账的方法
                    TransferMoney.transferMoney(accounts[fromAccount],accounts[toAccount],amount);
                }

            }
        }

        //开启20个线程进行转账
        for (int i = 0; i < NUM_THREADS; i++) {
    
    
            new TransferThread().start();
        }

    }


}

After running for a period of time, the program enters a blocking state.

Finding out the PID and

executing jstack 7464,
you can see that the following four threads are deadlocked.

Guess you like

Origin blog.csdn.net/qq_33229669/article/details/108526477