views:

1231

answers:

6

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).

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!”

+6  A: 

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 JCarder which is "an open source tool for finding potential deadlocks in concurrent multi-threaded Java programs".

Rich
+1 for jconsole and detect deadlocks.
Thorbjørn Ravn Andersen
+1  A: 

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.

For example, look at 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.

skaffman
A: 

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.

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.

Il-Bhima
+4  A: 

You can use a java.util.concurrent.Lock instead of the intrinsic Object locks. RentrantLock without fair ordering has the same basic behaviour and semantics as an intrinsic lock. There is a method tryLock that takes a timeout parameter:

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

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.

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. :

  > 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)
Steve B.
A: 

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

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

David Nouls