Wednesday, 3 August 2011

Java Thread Deadlocks

Generally deadlocks occur when two threads try to lock an object held by the counterpart thread.
Java has some internal locking mechanism, one of them is using synchronized keyword. When a thread enters into synchronized method, thread acquires object's lock, and releases the lock after leaving the synchronized method.
I think the deadlock issue in java can be visualized as below to understand better the issue.

Thread Deadlock















Here is a junit code for generating  a java deadlock.
import junit.framework.Assert;
import org.junit.Test;

/**
 * @author asahin
 */
public class ThreadTests {

    @Test
    public void testDeadLock() throws InterruptedException {

        final Writer writer = new Writer();
        final Reader reader = new Reader();
        writer.setReader(reader);
        reader.setWriter(writer);

        Thread readerThread = new Thread(new Runnable() {
            public void run() {
                try {
                    reader.readerOperation();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread writerThread = new Thread(new Runnable() {
            public void run() {
                try {
                    writer.writerOperation();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        readerThread.start();
        writerThread.start();

        readerThread.join(5000);
        writerThread.join(5000);
        Assert.assertTrue("Expecting readerThread alive", readerThread.isAlive());
        Assert.assertTrue("Expecting writerThread alive", writerThread.isAlive());
    }

    public static class Reader {
        public void setWriter(Writer writer) {
            this.writer = writer;
        }

        private Writer writer;

        public synchronized void readerOperation() throws InterruptedException {
            //rest little bit
            Thread.sleep(1000);
            System.out.println("Thread using Reader is:" + Thread.currentThread());
            writer.writerOperation();
        }

    }

    public static class Writer {
        private Reader reader;

        public void setReader(Reader reader) {
            this.reader = reader;
        }

        public synchronized void writerOperation() throws InterruptedException {
            //rest little bit
            Thread.sleep(1000);
            System.out.println("Thread using Writer is:" + Thread.currentThread());
            reader.readerOperation();
        }
    }

}

Verification of deadlock

Thread[readerThread,5,main] inside Reader
Thread[writerThread,5,main] inside Writer
2011-08-03 13:28:26
Full thread dump Java HotSpot(TM) Client VM (19.1-b02 mixed mode, sharing):
....
....
....
Found one Java-level deadlock:
=============================
"writerThread":
  waiting to lock monitor 0x01b1d99c (object 0x23d51640, a tr.asahin.ThreadTests$Reader),
  which is held by "readerThread"
"readerThread":
  waiting to lock monitor 0x01b18cc4 (object 0x23d4f960, a tr.asahin.ThreadTests$Writer),
  which is held by "writerThread"

Java stack information for the threads listed above:
===================================================
"writerThread":
 at tr.asahin.ThreadTests$Reader.readerOperation(ThreadTests.java:57)
 - waiting to lock <0x23d51640> (a tr.asahin.ThreadTests$Reader)
 at tr.asahin.ThreadTests$Writer.writerOperation(ThreadTests.java:75)
 - locked <0x23d4f960> (a tr.asahin.ThreadTests$Writer)
 at tr.asahin.ThreadTests$2.run(ThreadTests.java:32)
 at java.lang.Thread.run(Thread.java:662)
"readerThread":
 at tr.asahin.ThreadTests$Writer.writerOperation(ThreadTests.java:73)
 - waiting to lock <0x23d4f960> (a tr.asahin.ThreadTests$Writer)
 at tr.asahin.ThreadTests$Reader.readerOperation(ThreadTests.java:59)
 - locked <0x23d51640> (a tr.asahin.ThreadTests$Reader)
 at tr.asahin.ThreadTests$1.run(ThreadTests.java:22)
 at java.lang.Thread.run(Thread.java:662)

Found 1 deadlock.


2 comments:

  1. Nice Article on java Dead lock stuff. How do you detect dead locks in real time ?

    -Anil.

    ReplyDelete
  2. get thread dumps by
    kill -3 pid
    Ctrl+Break
    jconsole

    http://download.oracle.com/javase/6/docs/api/java/lang/management/ThreadMXBean.html#findDeadlockedThreads%28%29

    ReplyDelete