3

Does anybody know if it's possible to know name (or another info) about thread who currently hold the lock? I mean, for example:

public class State {
    private int i;
    synchronized int get() {return i;}
    synchronized void set(int i) {this.i = i;};
}

class MyThread extends Thread {
    State s;
    MyThread(State s) {
        this.s = s;
    }
    @Override
    public void run() {
        s.get();
    }
}

and let several MyThread's trying to call get() which is locked - how to know who actually locked it? Thank you!

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
Dmitry Adonin
  • 1,064
  • 3
  • 16
  • 36

1 Answers1

1

Its really a nice question, we can definitely use Thread.holdLocks(obj), It is really useful but there is a limitation that we can only know that whether current thread is holding lock on the passed object or not. But as per question, we want to have some mechanism so that we can find that which thread, if any, is holding lock on a given object.

As of now I can think of two below ways:

  1. jconsole

There is a jconsole utility present jdk's bin directory. We can get the information about the threads and their statuses(WAITING, Blocked etc.). Below is the example:

Suppose we have below class:

public class ThreadLockTest {
    private int i = 11;
    public static void main(String[] args) {
        ThreadLockTest obj = new ThreadLockTest();
        TestRunner runner = new TestRunner(obj);
        Thread t1 = new Thread(runner, "t1");
        Thread t2 = new Thread(runner, "t2");
        t1.start();
        t2.start();
    }

    public synchronized int getI() {
        try {
            System.out.println(Thread.currentThread().getName()+" starting wait");
            for(;;) {
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return i;
    }

    public synchronized void setI(int i) {
        this.i = i;
    }

    private static class TestRunner implements Runnable {
        private ThreadLockTest obj;
        private TestRunner(ThreadLockTest obj) {
            this.obj = obj;
        }
        @Override
        public void run() {
            System.out.println("i: "+obj.getI());
        }
    }
}

Run the above program, and then open the jconsole, and connect it to your program process. Now see the below screenshots of jconsole, in my case thread "t1" is holding lock ,and thread "t2" is waiting on it. You can see the message in jconsole which is clearly showing that which thread is waiting on which lock, and which thread is owning that lock. You can even use jconsole to detect deadlocks, if any.

enter image description here

In below screenshot, you can see the message which is clearly showing that, thread t2 is blocked for the lock which is owned by thread t1.

enter image description here

  1. Maintain a Object-Thread Map:

Here, we can maintain a map of < Object,Thread >, where the Thread is currently holding lock on this object. This approach is not really a good approach, but as we have java API limitation as there is no API which can tell which thread is holding lock on any object. SO in this approach, what we will do is, we will have a public Map, and for an object for which we are interested to know about the thread which currently holding lock on it, everytime we enter any synchronized method, we will make an entry in the Map, and when we exit from this synchronized method, we will remove the entry from Map. Like below

public synchronized void anyMethod() {
    MAP.put(this,Thread.currentThread());
    .................
    ................
    Map.remove(this);
}

I know this approach is having many many drawbacks, but if we really need to know about the thread which is holding lock on any object and we do not want to use jconsole, we can think of something like this approach. I know this approach will make the code dirty. So try to avoid it as much as you can, and just use jconsole to check the thread statuses and even for detecting deadlocks, if any.

I will strongly recommend to use jconsole, if you really need to know about which threads are blocked on which locks.

pbajpai
  • 1,303
  • 1
  • 9
  • 24
  • Thank's for such a detailed answer! Actually, keeping in mind possibility of jconsole to show info about deadlocks inspired me to ask such a question - I was interested how to do it programmatically with core Java facilities, not only for deadlocks, but for livelocks f.e. Anyway you proposed nice approach with map, should be tried. – Dmitry Adonin Oct 19 '16 at 13:51