java 如何检测死锁?同步块超时?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1194606/
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-10-29 15:34:43  来源:igfitidea点击:

How to detect deadlock ? Timeout in synchronized block?

javamultithreadingdeadlock

提问by Dani Cricco

I'm debugging a Java application that runs several threads. After a while of watching the log it seems that one of those threads is not running anymore. My guess is that the thread is waiting for a lock that is never released (the last output is before calling a synchronized method).

我正在调试运行多个线程的 Java 应用程序。看了一会儿日志后,似乎其中一个线程不再运行。我的猜测是线程正在等待一个永远不会释放的锁(最后一个输出是在调用同步方法之前)。

Can I configure a timeout to the thread; a sort of “wait for this lock but if it not available after 10 seconds don't wait anymore!”

我可以为线程配置超时吗?一种“等待这个锁,但如果它在 10 秒后不可用,就不要再等待了!”

回答by Ben Lings

You can use a java.util.concurrent.Lockinstead of the intrinsic Objectlocks. RentrantLockwithout fair ordering has the same basic behaviour and semantics as an intrinsic lock. There is a method tryLockthat takes a timeout parameter:

您可以使用java.util.concurrent.Lock而不是内在Object锁。没有公平排序的RentrantLock具有与内在锁相同的基本行为和语义。有一个方法tryLock需要一个超时参数:

Lock lock = ...;
if (lock.tryLock(10L, TimeUnit.SECONDS)) {
    try {
        // manipulate protected state
    } finally {
        lock.unlock();
    }
} else {
      // perform alternative actions
}

回答by Rich

Rather than adding extra code for debugging, you could use a debugging tool or profiler.

您可以使用调试工具或分析器,而不是添加额外的调试代码。

One option is to use something like JConsole (comes with the JDK) which includes a button called "Detect Deadlock" (at least it does in Java 6, I don't think it works in Java 5). Another option is to generate a thread dump to the console - on Unix you can type "kill -3 " while on Windows CTRL+BRK will work. Other profiling tools such as VisualVM (also in the JDK) can help. Finally there is JCarderwhich is "an open source tool for finding potential deadlocks in concurrent multi-threaded Java programs".

一种选择是使用 JConsole(与 JDK 一起提供)之类的东西,其中包括一个名为“检测死锁”的按钮(至少在 Java 6 中是这样,我认为它在 Java 5 中不起作用)。另一种选择是向控制台生成线程转储 - 在 Unix 上您可以键入“kill -3”,而在 Windows 上 CTRL+BRK 将起作用。其他分析工具,如 VisualVM(也在 JDK 中)可以提供帮助。最后是JCarder,它是“一种用于在并发多线程 Java 程序中查找潜在死锁的开源工具”。

回答by Steve B.

You can have the threads share an explicit lock (see java.util.concurrent.lock.Lock). You can then use Lock.tryLock(), which can take an optional timeout.

您可以让线程共享一个显式锁(请参阅 java.util.concurrent.lock.Lock)。然后您可以使用 Lock.tryLock(),它可以采用可选的超时时间。

You can also use the jstack utility that comes with java 1.6 (not sure about 1.5) which will print out the state of all of your threads and what they may or may not be waiting for. Just call it with the process id. eg. :

您还可以使用 java 1.6(不确定是否为 1.5)附带的 jstack 实用程序,它将打印出所有线程的状态以及它们可能等待或可能不等待的内容。只需使用进程 ID 调用它即可。例如。:

  > jstack PID 

        "Signal Dispatcher" daemon prio=10 tid=0x00000000408e8400 nid=0x79a8 runnable [0x0000000000000000..0x000000004143f810]
           java.lang.Thread.State: RUNNABLE

        "Finalizer" daemon prio=10 tid=0x00000000408c9400 nid=0x79a7 in Object.wait() [0x0000000041a7b000..0x0000000041a7bb00]
           java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00007f992d1e7050> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
            - locked <0x00007f992d1e7050> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
            at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

        "Reference Handler" daemon prio=10 tid=0x00000000408c2000 nid=0x79a6 in Object.wait() [0x000000004197a000..0x000000004197ac80]
           java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00007f992d41a958> (a java.lang.ref.Reference$Lock)
            at java.lang.Object.wait(Object.java:485)
            at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
            - locked <0x00007f992d41a958> (a java.lang.ref.Reference$Lock)

回答by David Nouls

There can be 2 reasons: 1) The thread died 2) The thread is locked somewhere or doing something you did not anticipate.

可能有 2 个原因:1) 线程死了 2) 线程被锁定在某处或做了一些您没有预料到的事情。

The best solution is to always use a debugger (wait until the situation occurs and then pauze the applications) or use JConsole/JStack/JVisualVM.

最好的解决方案是始终使用调试器(等到情况发生,然后暂停应用程序)或使用 JConsole/JStack/JVisualVM。

回答by skaffman

You can't use timeouts with traditionally synchronized methods. However, using the "new" java.util.concurrent stuff, you can use programatic locks that have timeout support.

您不能在传统同步方法中使用超时。但是,使用“新的” java.util.concurrent 东西,您可以使用具有超时支持的程序锁。

For example, look at java.util.concurrent.locks.ReentrantLock

比如看java.util.concurrent.locks.ReentrantLock

A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.

可重入互斥锁与使用同步方法和语句访问的隐式监视器锁具有相同的基本行为和语义,但具有扩展功能。

回答by Il-Bhima

While it is possible have timeouts while waiting for locks on synchronized methods, implementing these is unwieldy. Basically you would spawn a timer thread which would interrupt the block thread after T seconds...not nice.

虽然在等待同步方法上的锁时可能会超时,但实现这些很笨拙。基本上你会产生一个定时器线程,它会在 T 秒后中断块线程......不好。

If you're using Java 5 or higher I strongly suggest you see what the new concurrency classes offer. For example, you might consider using the ReentrantLock, which has a method tryLock(long timeout, TimeUnit unit)which will allow you to attempt to acquire the lock but allows you to escape after a fixed amount of time.

如果您使用的是 Java 5 或更高版本,我强烈建议您查看新的并发类提供的内容。例如,您可能会考虑使用ReentrantLock,它有一个tryLock(long timeout, TimeUnit unit) 方法,它允许您尝试获取锁,但允许您在固定时间后退出。

回答by Sanju Thomas

You can use Java Management Extension (JMX) API to figure out dead lock in java. Check out http://ourownjava.com/how-to-identify-deadlock-in-javafor an example.

您可以使用 Java 管理扩展 (JMX) API 来找出 Java 中的死锁。以http://ourownjava.com/how-to-identify-deadlock-in-java为例。