持有锁的当前线程的定义

时间:2016-10-19 11:58:21

标签: java multithreading concurrency

有人知道是否可以知道当前持有锁的线程的名称(或其他信息)?我的意思是,例如:

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();
    }
}

让几个MyThread尝试调用被锁定的get() - 如何知道谁实际锁定了它?谢谢!

1 个答案:

答案 0 :(得分:1)

它真的是一个很好的问题,我们绝对可以使用Thread.holdLocks(obj),它确实非常有用但是我们只能知道当前线程是否对传递的对象保持锁定存在限制。但是根据问题,我们希望有一些机制,以便我们可以找到哪个线程(如果有的话)对给定对象保持锁定。

截至目前,我可以想到以下两种方式:

  
      
  1. jconsole
  2.   

jconk实用程序存在jdk的bin目录。我们可以获得有关线程及其状态的信息(WAITING,Blocked等)。以下是示例:

假设我们有以下课程:

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());
        }
    }
}

运行上述程序,然后打开jconsole,并将其连接到您的程序进程。现在看看jconsole的下面截图,在我的情况下线程" t1"持有锁,线程" t2"正在等待它。您可以在jconsole中看到消息,该消息清楚地显示哪个线程正在等待哪个锁,以及哪个线程拥有该锁。您甚至可以使用jconsole来检测死锁(如果有的话)。

enter image description here

在下面的屏幕截图中,您可以看到清楚显示的消息,线程t2被线程t1拥有的锁阻塞。

enter image description here

  
      
  1. 维护对象 - 线程映射:
  2.   

在这里,我们可以维护<对象,线程>,其中Thread当前持有对此对象的锁定。这种方法并不是一个很好的方法,但因为我们有java API限制,因为没有API可以告诉哪个线程在任何对象上持有锁。在这种方法中,我们将要做的是,我们将有一个公共Map,对于我们有兴趣了解当前持有锁定的线程的对象,每次我们输入任何同步方法时,我们将制作一个在Map中输入,当我们从这个synchronized方法退出时,我们将从Map中删除该条目。如下所示

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

我知道这种方法有许多缺点,但是如果我们真的需要知道对任何对象持有锁的线程并且我们不想使用jconsole,我们可以想到类似这种方法的东西。我知道这种方法会使代码变脏。因此,尽量避免使用它,只需使用jconsole检查线程状态,甚至检测死锁(如果有的话)。

我强烈建议您使用jconsole,如果您确实需要知道哪些线程被锁定在哪个锁上。