`
hbxflihua
  • 浏览: 660370 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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

阅读更多

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

 

定位死锁最常见的方式就是利用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、使用带超时的方法,为程序带来更多的可控性。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics