线程死锁相关问题及处理

线程死锁会导致线程阻塞,若有大量线程阻塞,将会导致线程资源被耗尽,最终会导到系统崩溃,无法对外服务。

发现线程死锁,需要依赖监控系统。监控系统可以定时使用jstack 命令采集线程信息,jstack命令中可以查看到死锁的详细信息,进行告警或者人工介入干预等。

代码示例:

public class DeadlockTest {
    // 创建两个共享资源
    private static final String resource1 = new String();
    private static final Object resource2 = new Object();
 
    public static void main(String[] args) {
        /**
         * 两个线程 thread1 thread2
         * thread1对resource1上锁,然后尝试获取resource2的锁;
         * thread2对resource2上锁,然后尝试获取resource1的锁;
         * 2个线程会相互等待,出现死锁
         */
        Thread thread1 = new Thread(() -> {
            synchronized (resource1) {
                System.out.println("Thread 1: 锁定resource1");
 
                try {
                    Thread.sleep(100); // 假设这里有其他操作,需要一些时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                System.out.println("Thread 1: 尝试索取resource2的锁");
 
                //尝试索取resource2的锁
                synchronized (resource2) {
                    System.out.println("Thread 1: 锁定 resource2");
                }
            }
        }, "thread1");
 
        Thread thread2 = new Thread(() -> {
            synchronized (resource2) {
                System.out.println("Thread 2: 锁定 resource2");
 
                try {
                    Thread.sleep(100); // 假设这里有其他操作,需要一些时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                //尝试索取resource1的锁
                System.out.println("Thread 2: 尝试索取resource1的锁");
                synchronized (resource1) {
                    System.out.println("Thread 2: 锁定 resource1");
                }
            }
        }, "thread2");
 
        // 启动线程
        thread1.start();
        thread2.start();
    }
}

定位死锁代码

1、方法一:jps+jstack

jps:jdk自带工具,可以查看所有的java进程

线程死锁相关问题及处理

示例代码进程id是2504。

jstack:查看命令死锁信息,jdk自带的工具,可以查看某个java进程中所有的线程快照,可以看到死锁的相关信息。使用方式:jstack 进程id

执行jstack 2504,从输出结果中得到thread1和thread2死锁的代码位置:

线程死锁相关问题及处理

2、方式二:jvisualvm

jvisualvm工具:jdk自带的工具。在cmd中运行jvisualvm,就可以打开这个工具。

线程死锁相关问题及处理

使用方式:

线程死锁相关问题及处理

线程死锁相关问题及处理

3、方式三:arthas

阿里开源的工具,特别好用的一个jvm线上问题诊断工具。

详情见:
https://arthas.aliyun.com/doc/quick-start.html

下载解压:

线程死锁相关问题及处理

在cmd运行: java -jar arthas-boot.jar

线程死锁相关问题及处理

如图,输入4:

线程死锁相关问题及处理

输入thread -b,得到thread1的id是22,thread2的id是23:

线程死锁相关问题及处理

线程死锁相关问题及处理

死锁常见的解决方案

  • 避免使用多个锁:通过合理设计程序,尽量避免多个线程同时争用一样的资源
  • 保持锁的有序性:当使用多个锁时,保持所有线程获取锁的顺序一致,以避免因顺序不一致导致的死锁。
  • 超时等待:设置锁的超时时间,当等待超过必定时间后,放弃对锁的请求,进行其他的处理。
  • 死锁检测和恢复:使用工具来检测和恢复死锁,一旦检测到死锁,可以通过中断线程、释放资源等方式来恢复程序的执行。
© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容