当前位置:网站首页>并发编程 — 死锁排查及处理

并发编程 — 死锁排查及处理

2022-07-05 06:40:00 搬运Gong

前言

相信不少程序员在工作中都遇到过死锁这种场景,比如数据库死锁、应用程序死锁。那么大家都是如何来处理这种情况的呢?本文将通过一个简单的案例来进行梳理相关思路及解决方案,希望可以帮到遇到类似情况的童鞋。

 1. 什么是死锁?

死锁是指两个或者两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力干涉那它们都将无法推进下去,如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。

 

产生死锁的主要原因:

① 系统资源不足;

② 进程运行推荐的顺序不合时候;

③ 资源分配不当;

2. 手写一个死锁的 case案例

上面我们知道了什么是死锁以及死锁产生的条件,那么来通过手写一个案例来体验一下死锁:

	public static void main(String[] args) {
		final Object objectA = new Object();
		final Object objectB = new Object();

		new Thread(() -> {
			synchronized (objectA) {
				System.out.println("线程 " + Thread.currentThread().getName() + " 启动,持有 A锁...");
				try {
					TimeUnit.SECONDS.sleep(1L);
					synchronized (objectB) {
						System.out.println("线程 " + Thread.currentThread().getName() + " 尝试获取 B 锁,成功!!");
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"A").start();

		new Thread(() -> {
			synchronized (objectB) {
				System.out.println("线程 " + Thread.currentThread().getName() + " 启动,持有 B锁...");
				try {
					TimeUnit.SECONDS.sleep(1L);
					synchronized (objectA) {
						System.out.println("线程 " + Thread.currentThread().getName() + " 尝试获取 A 锁,成功!!");
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		},"B").start();
	}

可以看到,两个线程互相争抢资源,导致死锁产生,程序处于一直运行阶段,无法结束。

3. 死锁排查

        通过手写的死锁 case,知道了存在死锁,那么真实的生产环境是无法定位到是不是真的出现了死锁情况的,比如写了一个 while(true) {} 无限循环一段代码块。

3.1 命令行排查

        如何定位产生了死锁呢?很简单,使用JDK 自带的命令- jstack 来查看 JVM 的堆栈信息:

① jps -查看正在运行的 Java 进程;

② jstack 进程 ID;

 

 通过输出的信息可以看到,检查到了死锁,并且指出了具体产生死锁的代码行数。

 3.2 图形界面排查

        还有另外一种方式来排查死锁,也是 JDK 提供的一个图形化的命令 jconsole,通过这个命令可以连接到具体的Java 进程,在图形化中进行查看。

 

两种方式,都可以定位到死锁出现的位置。定位到位置后,优化程序规避死锁即可(通过死锁产生的原因进行规避)。

        以上,是两种最简单也最实用的排查死锁的方法,在真实的生产环境遇到程序卡顿、无响应的时候,可通过这种方式来排查是否是因为产生了死锁占用大量资源不释放导致的。

 

原网站

版权声明
本文为[搬运Gong]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_20315217/article/details/125572034