Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect deadlock ? Timeout in synchronized block?

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

like image 562
Dani Cricco Avatar asked Jul 28 '09 14:07

Dani Cricco


People also ask

Can synchronized cause deadlock?

Deadlock occurs when multiple threads need the same locks but obtain them in different order. A Java multithreaded program may suffer from the deadlock condition because the synchronized keyword causes the executing thread to block while waiting for the lock, or monitor, associated with the specified object.

Can synchronization avoid deadlock?

If you have two independent attribute in a class shared by multiple threads, you must synchronized the access to each variable, but there is no problem if one thread is accessing one of the attribute and another thread accessing the other at the same time. Synchronize does not prevent deadlock.

How can we avoid deadlocks without using synchronized methods?

For example, instead of using synchronized ArrayList use the ConcurrentLinkedQueue. Avoid Nested Locks: Another way to avoid deadlock is to avoid giving a lock to multiple threads if we have already provided a lock to one thread. Since we must avoid allocating a lock to multiple threads. Using Thread.

Why must wait () always be in synchronized block?

As Michael Borgwardt points out, wait/notify is all about communication between threads, so you'll always end up with a race condition similar to the one described above. This is why the "only wait inside synchronized" rule is enforced.


3 Answers

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
}
like image 153
Ben Lings Avatar answered Oct 16 '22 16:10

Ben Lings


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

like image 10
Rich Avatar answered Oct 16 '22 17:10

Rich


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)
like image 3
Steve B. Avatar answered Oct 16 '22 17:10

Steve B.