欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

什么情况下Java程序会产生死锁?如何定位和修复死锁

程序员文章站 2022-03-07 10:02:18
...

死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进。死锁不仅仅是在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于相互持有对方需要的锁,而永久处于阻塞的状态。

 

定位死锁最常见的方式就是利用jstack等工具获取线程栈,然后定位相互之间的依赖关系,进而找到死锁。如果是比较明显的死锁,往往jstack等就能直接定位,类似jconsole甚至可以在图形界面进行有限的死锁检测。

 

如果程序运行时发生了死锁,绝大多数情况下都是无法在线解决的,只能重启、修正程序本身的问题。所以,代码开发阶段玄乎审查,或者利用工具进行预防性排查,往往也是很重要的。

 

Java提供了标准的管理API-ThreadMXBean来进行死锁的定位跟踪,示例代码如下:

 

public static void main(String[] args) throws InterruptedException {

	ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
	Runnable dlCheck = new Runnable() {

    	@Override
    	public void run() {
        	long[] threadIds = mbean.findDeadlockedThreads();
        	if (threadIds != null) {
                     ThreadInfo[] threadInfos = mbean.getThreadInfo(threadIds);
                     System.out.println("Detected deadlock threads:");
            	for (ThreadInfo threadInfo : threadInfos) {
                	System.out.println(threadInfo.getThreadName());
            	}
          }
       }
    };

       ScheduledExecutorService scheduler =Executors.newScheduledThreadPool(1);
       // 稍等 5 秒,然后每 10 秒进行一次死锁扫描
        scheduler.scheduleAtFixedRate(dlCheck, 5L, 10L, TimeUnit.SECONDS);
// 死锁样例代码…
}

 

 需要注意的是,对线程进行快照本身是一个相对重量级的操作,需要慎重选择频度和时机。

 

如何在程序中尽量避免死锁?

1、如果可能,尽量避免使用多个锁,并且只有在需要时才持有锁,嵌套synchronizedlock很容易产生死锁。

2、如果必须使用多个锁,尽量设计好锁的获取顺序。

3、使用带超时的方法,为程序带来更多的可控性。

相关标签: java