当前位置:  开发笔记 > 编程语言 > 正文

Java中的死锁检测

如何解决《Java中的死锁检测》经验,为你挑选了5个好方法。

很久以前,我从Java参考书中保存了一句话:"Java没有处理死锁的机制.它甚至不知道发生了死锁." (Head First Java 2nd Edition,p.516)

那么,它是什么呢?有没有办法在Java中捕获死锁案例?我的意思是,有没有一种方法可以让我们的代码了解发生死锁的情况?



1> staffan..:

从JDK 1.5开始,java.lang.management包中有非常有用的方法来查找和检查发生的死锁.见findMonitorDeadlockedThreads()findDeadlockedThreads()该方法ThreadMXBean的类.

使用它的一种可能方法是使用单独的监视程序线程(或定期任务)来执行此操作.

示例代码:

  ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
  long[] ids = tmx.findDeadlockedThreads();
  if (ids != null) {
     ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
     System.out.println("The following threads are deadlocked:");
     for (ThreadInfo ti : infos) {
        System.out.println(ti);
     }
  }



2> Steve K..:

JConsole能够检测正在运行的应用程序中的死锁.



3> Alex Miller..:

JDK 5和6将把持有的锁信息转储到完整的线程转储中(使用kill -3,jstack,jconsole等获得).JDK 6甚至包含有关ReentrantLock和ReentrantReadWriteLock的信息.从这些信息中可以通过找到锁定周期来诊断死锁:线程A保持锁定1,线程B保持锁定2,并且A正在请求2或B正在请求1.根据我的经验,这通常是非常明显的.

其他分析工具实际上可以找到潜在的死锁,即使它们没有发生.来自OptimizeIt,JProbe,Coverity等供应商的线程工具是很好看的地方.



4> Dave Griffit..:

请注意,使用并发包非常难以调试的死锁类型.这就是你有一个ReentrantReadWriteLock并且一个线程抓住读锁定然后(比方说)试图进入一个其他线程持有的监视器,该线程也在等待抓取写锁定.使调试特别困难的原因是没有人输入读锁的记录.这只是一个计数.该线程甚至可能抛出异常而死亡,使读取计数不为零.

下面是前面提到的findDeadlockedThreads方法无法获得的示例死锁:

import java.util.concurrent.locks.*;
import java.lang.management.*;

public class LockTest {

    static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String[] args) throws Exception {
        Reader reader = new Reader();
        Writer writer = new Writer();
        sleep(10);
        System.out.println("finding deadlocked threads");
        ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
        long[] ids = tmx.findDeadlockedThreads();
        if (ids != null) {
            ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
            System.out.println("the following threads are deadlocked:");
            for (ThreadInfo ti : infos) {
                System.out.println(ti);
            }
        }
        System.out.println("finished finding deadlocked threads");
    }

    static void sleep(int seconds) {
        try {
            Thread.currentThread().sleep(seconds*1000);
        } catch (InterruptedException e) {}
    }

    static class Reader implements Runnable {
        Reader() {
            new Thread(this).start();
        }
        public void run() {
            sleep(2);
            System.out.println("reader thread getting lock");
            lock.readLock().lock();
            System.out.println("reader thread got lock");
            synchronized (lock) {
                System.out.println("reader thread inside monitor!");
                lock.readLock().unlock();
            }
        }
    }

    static class Writer implements Runnable {
        Writer() {
            new Thread(this).start();
        }
        public void run() {
            synchronized (lock) {
                sleep(4);
                System.out.println("writer thread getting lock");
                lock.writeLock().lock();
                System.out.println("writer thread got lock!");
            }
        }
    }
}



5> luke..:

通常,java不提供死锁检测.与使用显式锁定的语言相比,synchronized关键字和内置监视器使得解决死锁更加困难.

我建议迁移到使用java.util.concurrent.Lock锁等,以使您的锁定方案更容易推理.实际上,您可以轻松地使用死锁检测自行实现锁定接口.该算法基本上遍历锁依赖图并寻找一个循环.


java.util.concurrent.Lock中的锁具有从JDK 1.6开始内置的死锁检测.请参阅java.lang.management.ThreadMXBean.
推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有