【问题标题】:Definition of current thread who hold the lock当前持有锁的线程的定义
【发布时间】:2016-10-19 11:58:20
【问题描述】:

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

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() - 如何知道谁实际锁定了它?谢谢!

【问题讨论】:

  • 感谢您的快速回复!这是有用的提示,应该调查...
  • @DmitryAdonin 'who' 表示线程的名称(变量名)??
  • @Supun Wijerathne 是的,开始一个线程并试图持有锁我想知道有关阻止我持有对象锁定的线程的任何信息

标签: java multithreading concurrency


【解决方案1】:

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

目前我能想到以下两种方式:

  1. jconsole

jdk 的 bin 目录中有一个 jconsole 实用程序。我们可以获得有关线程及其状态(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 来检测死锁(如果有的话)。

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

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

在这里,我们可以维护一个 的映射,其中 Thread 当前持有该对象的锁。这种方法并不是一个真正的好方法,但由于我们有 java API 限制,因为没有 API 可以判断哪个线程在任何对象上持有锁。所以在这种方法中,我们要做的是,我们将有一个公共 Map,对于一个我们有兴趣了解当前持有锁的线程的对象,每次我们进入任何同步方法时,我们都会做一个Map 中的条目,当我们退出此同步方法时,我们将从 Map 中删除该条目。如下所示

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

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

如果您确实需要了解哪些线程在哪些锁上被阻塞,我强烈建议您使用 jconsole。

【讨论】:

  • 感谢您提供如此详细的回答!实际上,记住 jconsole 显示有关死锁的信息的可能性激发了我提出这样一个问题 - 我很感兴趣如何使用核心 Java 工具以编程方式进行操作,不仅针对死锁,而且针对活锁 f.e.无论如何,您提出了很好的地图方法,应该尝试。
猜你喜欢
  • 1970-01-01
  • 2015-05-03
  • 2016-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 1970-01-01
  • 2012-07-08
相关资源
最近更新 更多