以编程方式确定哪个 Java 线程持有锁

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50561/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:39:55  来源:igfitidea点击:

Programmatically determine which Java thread holds a lock

javamultithreadingconcurrency

提问by Johan Lübcke

Is it possible at runtime to programmatically check the name of the Thread that is holding the lock of a given object?

是否可以在运行时以编程方式检查持有给定对象锁的线程的名称?

采纳答案by erickson

You can only tell whether the current thread holds a normal lock (Thread.holdsLock(Object)). You can't get a reference to the thread that has the lock without native code.

您只能判断当前线程是否持有普通锁 ( Thread.holdsLock(Object))。如果没有本机代码,您将无法获得对具有锁的线程的引用。

However, if you're doing anything complicated with threading, you probably want to familiarize yourself with the java.util.concurrent packages. The ReentrantLockdoes allow you to get its owner (but its a protected method, so you'd have to extend this). Depending on your application, it may well be that by using the concurrency packages, you'll find that you don't need to get the lock's owner after all.

但是,如果您正在做任何复杂的线程处理,您可能需要熟悉 java.util.concurrent 包。该ReentrantLock确实让你得到它的所有者(但其受保护的方法,所以你必须要扩展这个)。根据您的应用程序,很可能通过使用并发包,您会发现您根本不需要获取锁的所有者。

There are non-programmatic methods to find the lock owners, such as signaling the JVM to issue a thread dump to stderr, that are useful to determine the cause of deadlocks.

有一些非编程方法可以找到锁所有者,例如向 JVM 发出信号以向 stderr 发出线程转储,这对于确定死锁的原因很有用。

回答by Todd

Run jconsole. It is included in the Java SDK and is run from the command line. I'm not sure what OS you are using, but on windows you can just pass it the PID of the java process. It should help you find the thread that is causing the problem. Or, you can use a commercial profiler like YourKit or any number of other profilers.

运行jconsole。它包含在 Java SDK 中并从命令行运行。我不确定您使用的是什么操作系统,但在 Windows 上,您可以将 java 进程的 PID 传递给它。它应该可以帮助您找到导致问题的线程。或者,您可以使用像 YourKit 这样的商业分析器或任意数量的其他分析器。

回答by Tom Hawtin - tackline

You can, from 1.6, use JMX to do all sorts of interesting things including finding held locks. You can't get the actual object, but you do get the class and identity hash value (which is not unique).

从 1.6 开始,您可以使用 JMX 做各种有趣的事情,包括查找持有的锁。您无法获得实际对象,但您确实获得了类和身份哈希值(这不是唯一的)。

There's an example in one of my weblogs.

我的一个博客中有一个例子。

回答by Chris Kimpton

In 1.5, you can find all the threads and get each one's state, eg like this:

在 1.5 中,您可以找到所有线程并获取每个线程的状态,例如:

    Map<Thread,StackTraceElement[]> map = Thread.getAllStackTraces();
    for (Map.Entry<Thread, StackTraceElement[]> threadEntry : map.entrySet()) {
        log.info("Thread:"+threadEntry.getKey().getName()+":"+threadEntry.getKey().getState());
        for (StackTraceElement element : threadEntry.getValue()) {
            log.info("--> "+element);
        }
    }

Thread.getState gives you info about whether the thread is BLOCKED, WAITING etc, see jdk api ThreadState

Thread.getState 为您提供有关线程是否被 BLOCKED、WAITING 等的信息,请参阅jdk api ThreadState

回答by carrino

You can get at the locks held by threads with reflection. This only works with java 1.6.

您可以通过反射获取线程持有的锁。这仅适用于 java 1.6。

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] ti = bean.getThreadInfo(bean.getAllThreadIds(), true, true);

On each of these ThreadInfo objects there are LockInfo objects which you can use the identityHashCode on them to compare to the lock in question.

在每个 ThreadInfo 对象上都有 LockInfo 对象,您可以在它们上使用 identityHashCode 来与有问题的锁进行比较。

回答by dac2009

You can use a variable to hold the current thread when you take the lock, then print it if someone else is trying to use it.

您可以在获取锁时使用一个变量来保存当前线程,然后在其他人尝试使用它时打印它。

Thread holderOfLock = null;
Object theLock = new Object();

public void doStuff()
{
    if(holderOfLock != null)
    {
       //get and print name of holderOfLock-thread or get stacktrace etc.
    }

    synchronized (theLock)
    {
        holderOfLock = Thread.currentThread();
        //do stuff...
        holderOfLock = null;
    }
}

回答by NullPointer

You can check the lock on the particular object by calling wait()or notify()method on that object. If the object does not hold the lock, then it will throw llegalMonitorStateException.

您可以通过调用该对象上的wait()notify()方法来检查特定对象上的锁定。如果对象不持有锁,那么它会抛出llegalMonitorStateException

2- By calling holdsLock(Object o)method. This will return the boolean value.

2-通过调用holdsLock(Object o)方法。这将返回布尔值。

回答by ceph3us

if it is re -entrant locku can can check if it is held by current thread

如果是重入锁,你可以检查它是否被当前线程持有

final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();

回答by okwap

Ugly but works.

丑陋但有效。

String findLockOwner(ReentrantLock lock) {
    String patternStr = "\[Locked by thread (\S+)\]";
    Pattern pattern = Pattern.compile(patternStr);
    Matcher matcher = pattern.matcher(lock.toString());
    boolean matchFound = matcher.find();
    if (matchFound && matcher.groupCount() >= 1) {
      return matcher.group(1);
    }
}