java中的编程死锁检测

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1102359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:46:25  来源:igfitidea点击:

Programmatic deadlock detection in java

javamultithreadingconcurrencydeadlock

提问by

How can I programmaticallydetect that a deadlock has occurred in a Java program?

如何以编程方式检测 Java 程序中是否发生了死锁?

回答by RichardOD

You might want to consider IBM's MTRAT. Prevention is better than cure after all. The Multicore Software Development Kitalso comes with a deadlock detection tool.

您可能需要考虑IBM 的 MTRAT。毕竟预防胜于治疗。在多核软件开发工具包还带有一个死锁检测工具。

回答by Artem Barger

In case you want it to be done in run-time you can use watchdogfor that.

如果您希望它在运行时完成,您可以使用看门狗

回答by Nicolas Simonet

One useful hint for investigation:

一个有用的调查提示:

If you can catch the application red handed and suspect a deadlock has occurred, go and press "Ctrl-Break" in the java.exe console window (or "Ctrl-\" on Solaris/Linux). The jvm will dump the current status and stack trace of all threads, find out dead locks and precisely describe them.

如果您能发现应用程序并怀疑发生了死锁,请在 java.exe 控制台窗口中按“Ctrl-Break”(或在 Solaris/Linux 上按“Ctrl-\”)。jvm 将转储所有线程的当前状态和堆栈跟踪,找出死锁并精确描述它们。

It will look something like this:

它看起来像这样:

Full thread dump Java HotSpot(TM) Client VM (1.5.0_09-b03 mixed mode):

"[Test Timer] Request Queue" prio=6 tid=0x13d708d0 nid=0x1ec in Object.
    wait() [0x1b00f000..0x1b00fb68]
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Unknown Source)
    at library.util.AsyncQueue.run(AsyncQueue.java:138)
        - locked <0x02e70000> (a test.server.scheduler.SchedulerRequestQueue)

    ...

Found one Java-level deadlock:
=============================
"Corba service":
  waiting to lock monitor 0x13c06684 (object 0x04697d90, a java.lang.Object),
  which is held by "[Server Connection] Heartbeat Timer"
"[Server Connection] Heartbeat Timer":
  waiting to lock monitor 0x13c065c4 (object 0x0467e728, a test.proxy.ServerProxy), which is held by "Corba service"

Java stack information for the threads listed above:
===================================================
"Corba service":
    at test.proxy.ServerProxy.stopHBWatchDog(ServerProxy:695)
    - waiting to lock <0x04697d90> (a java.lang.Object)
    ...

回答by oxbow_lakes

If you don't require programmatic detection you can do this via the JConsole; on the thread tab there is a "detect deadlock" button. In JDK6 this detect locks for both intrinsic monitors and j.u.cLocks

如果您不需要编程检测,则可以通过JConsole执行此操作;在线程选项卡上有一个“检测死锁”按钮。在 JDK6 中,这会检测内部监视器和j.u.cLocks 的锁

Run up the JConsole via the $JAVA_HOM/bin/jconsolecommand

通过$JAVA_HOM/bin/jconsole命令运行 JConsole

回答by Adamski

You can do this programmatically using the ThreadMXBeanthat ships with the JDK:

您可以使用ThreadMXBeanJDK 附带的以编程方式执行此操作:

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads(); // Returns null if no threads are deadlocked.

if (threadIds != null) {
    ThreadInfo[] infos = bean.getThreadInfo(threadIds);

    for (ThreadInfo info : infos) {
        StackTraceElement[] stack = info.getStackTrace();
        // Log or store stack trace information.
    }
}

Obviously you should try to isolate whichever thread is performing this deadlock check - Otherwise if that thread deadlocks it won't be able to run the check!

显然,您应该尝试隔离正在执行此死锁检查的线程 - 否则,如果该线程死锁,它将无法运行检查!

Incidentally this is what JConsole is using under the covers.

顺便说一句,这就是 JConsole 在幕后使用的内容。

回答by Toby

tempus-fugitalso implements it along with a programmatic thread dumping class. It's implemented using the mbean mechanism mentioned above and offers a drop in, out-of-the-box super duper solution.

tempus-fugit还将它与编程线程转储类一起实现。它是使用上面提到的 mbean 机制实现的,并提供了一个即用型的、开箱即用的超级骗子解决方案。

回答by Aaron Digulla

There is code here: http://www.java2s.com/Code/Java/Development-Class/PerformingdeadlockdetectionprogrammaticallywithintheapplicationusingthejavalangmanagementAPI.htm

这里有代码:http: //www.java2s.com/Code/Java/Development-Class/PerformingdeadlockdetectionprogrammaticallywithintheapplicationusingthejavalangmanagementAPI.htm

The magic happens in ThreadMonitor.findDeadlock():

神奇发生在ThreadMonitor.findDeadlock()

  public boolean findDeadlock() {
    long[] tids;
    if (findDeadlocksMethodName.equals("findDeadlockedThreads")
        && tmbean.isSynchronizerUsageSupported()) {
      tids = tmbean.findDeadlockedThreads();
      if (tids == null) {
        return false;
      }

      System.out.println("Deadlock found :-");
      ThreadInfo[] infos = tmbean.getThreadInfo(tids, true, true);
      for (ThreadInfo ti : infos) {
        printThreadInfo(ti);
        printLockInfo(ti.getLockedSynchronizers());
        System.out.println();
      }
    } else {
      tids = tmbean.findMonitorDeadlockedThreads();
      if (tids == null) {
        return false;
      }
      ThreadInfo[] infos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
      for (ThreadInfo ti : infos) {
        // print thread information
        printThreadInfo(ti);
      }
    }

    return true;
  }

This calls an API of the ThreadMXBeanwhich has a different name in Java 5 and 6 (hence the outer if()).

这将调用ThreadMXBean在 Java 5 和 6 中具有不同名称的 的 API (因此是外部的if())。

The code example also allows to interrupt the locks, so you can even break the deadlock.

该代码示例还允许中断锁定,因此您甚至可以打破死锁。

回答by Tiago Cogumbreiro

JArmusis a library for deadlock detection and avoidance. It includes support for: Thread.join, CyclicBarrier, CountDownLatch, Phaser, and ReentrantLock.

JArmus是一个用于死锁检测和避免的库。它包括支持: Thread.joinCyclicBarrierCountDownLatchPhaser,和 ReentrantLock

To use JArmus you need to instrument your code. Either through one of its instrumented classes or automatically with the JArmus instrumentar jarmusc.

要使用 JArmus,您需要检测您的代码。通过其检测类之一或自动使用 JArmus 工具jarmusc

java -jar jarmusc.jar yourprogram.jar checkedprogram.jar

java -jar jarmusc.jar yourprogram.jar checkedprogram.jar

The input yourprogram.jaris the program you want to check. The output is the same program with checks to automatically find any deadlock.

输入yourprogram.jar是您要检查的程序。输出是同一个程序,带有自动查找任何死锁的检查。

Barriers need some help

障碍需要一些帮助

Verifying deadlocks with classes CyclicBarrier, CountDownLatch, Phaseris a bit tricky --- for example, JConsole cannot detect these types of deadlocks. JArmus needs a little help from you: you must specify which threads are influencing synchronization, we call these registeredthreads.

验证死锁与类CyclicBarrierCountDownLatchPhaser是有点麻烦---例如,JConsole的不能检测这些类型的死锁。JArmus 需要您的一些帮助:您必须指定哪些线程正在影响同步,我们将这些线程称为注册线程。

As soon as possible, the thread must mark itself as registered. A good place to mark registered threads is at the beginning method Runnable.run. JArmus.register(latch);

线程必须尽快将自己标记为已注册。标记注册线程的一个好地方是在开始方法Runnable.runJArmus.register(latch);

Example

例子

The following program that deadlocks is correctly identified by JArmus:

JArmus 正确识别了以下死锁程序:

final CountDownLatch latch = new CountDownLatch(2);
final CyclicBarrier barrier = new CyclicBarrier(2);
final Queue<Exception> exceptions = new ArrayDeque<>();
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            JArmus.register(barrier); // do not forget to register!
            JArmus.register(latch); // do not forget to register!
            latch.countDown();
            latch.await();
            barrier.await();
        } catch (Exception e) {
            exceptions.add(e);
        }
    }
});
Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            JArmus.register(barrier); // do not forget to register!
            JArmus.register(latch); // do not forget to register!
            barrier.await();
            latch.countDown();
            latch.await();
        } catch (Exception e) {
            exceptions.add(e);
        }
    }
});
t1.start();
t2.start();

回答by user2485429

You can detect the deadlocked threads programmatically using ThreadMXBean class.Here is the code,

您可以使用 ThreadMXBean 类以编程方式检测死锁线程。这是代码,

    ThreadMXBean bean = ManagementFactory.getThreadMXBean();

    long ids[] = bean.findMonitorDeadlockedThreads();

    if(ids != null)
    {
        ThreadInfo threadInfo[] = bean.getThreadInfo(ids);

        for (ThreadInfo threadInfo1 : threadInfo)
        {
            System.out.println(threadInfo1.getThreadId());    //Prints the ID of deadlocked thread

            System.out.println(threadInfo1.getThreadName());  //Prints the name of deadlocked thread

            System.out.println(threadInfo1.getLockName());    //Prints the string representation of an object for which thread has entered into deadlock.

            System.out.println(threadInfo1.getLockOwnerId());  //Prints the ID of thread which currently owns the object lock

            System.out.println(threadInfo1.getLockOwnerName());  //Prints name of the thread which currently owns the object lock.
        }
    }
    else
    {
        System.out.println("No Deadlocked Threads");
    }

Click herefor more info on how to detect the deadlocked threads.

单击此处了解有关如何检测死锁线程的更多信息。