Программно определить, какой поток Java удерживает блокировку

Возможно ли во время выполнения программно проверить имя потока, удерживающего блокировку данного объекта?


person Johan Lübcke    schedule 08.09.2008    source источник
comment
Пожалуйста, измените свой заголовок и сообщение, чтобы указать, что вы имеете в виду Java. Тег не должен быть единственным местом, где размещается важная информация, относящаяся к вопросу.   -  person Adam Davis    schedule 09.09.2008


Ответы (9)


Вы можете только определить, удерживает ли текущий поток обычную блокировку (Thread.holdsLock(Object)). Вы не можете получить ссылку на поток с блокировкой без собственного кода.

Однако, если вы делаете что-то сложное с многопоточностью, вы, вероятно, захотите ознакомиться с пакетами java.util.concurrent. ReentrantLock позволяет вам чтобы получить его владельца (но это защищенный метод, поэтому вам придется его расширить). В зависимости от вашего приложения вполне может случиться так, что, используя пакеты параллелизма, вы обнаружите, что вам не нужно в конце концов получать владельца блокировки.

Существуют непрограммные методы поиска владельцев блокировок, такие как сигнализация JVM о выдаче дампа потока в stderr, которые полезны для определения причины взаимоблокировок.

person erickson    schedule 08.09.2008

Вы можете добраться до замков, удерживаемых нитями, с помощью отражения. Это работает только с java 1.6.

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

В каждом из этих объектов ThreadInfo есть объекты LockInfo, для которых вы можете использовать identityHashCode для сравнения с рассматриваемой блокировкой.

person carrino    schedule 04.09.2009

Начиная с версии 1.6, вы можете использовать JMX для выполнения всевозможных интересных задач, включая поиск удерживаемых блокировок. Вы не можете получить фактический объект, но вы получаете хеш-значение класса и идентификатора (которое не является уникальным).

В одном из моих блогов есть пример.

person Tom Hawtin - tackline    schedule 09.09.2008

Запустите jconsole. Он включен в Java SDK и запускается из командной строки. Я не уверен, какую ОС вы используете, но в Windows вы можете просто передать ей PID процесса Java. Это должно помочь вам найти поток, который вызывает проблему. Или вы можете использовать коммерческий профилировщик, такой как YourKit, или любое количество других профилировщиков.

person Todd    schedule 09.09.2008

В версии 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 предоставляет информацию о том, заблокирован ли поток, ОЖИДАЕТ ли его и т. д., см. jdk API ThreadState

person Chris Kimpton    schedule 09.09.2008

если это блокировка повторного входа, вы можете проверить, удерживается ли она текущим потоком

final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();
person ceph3us    schedule 11.07.2015

Вы можете проверить блокировку конкретного объекта, вызвав метод wait() или notify() для этого объекта. Если объект не удерживает блокировку, он выдаст llegalMonitorStateException .

2- Вызовом метода holdsLock(Object o). Это вернет логическое значение.

person NullPointer    schedule 07.03.2013

Вы можете использовать переменную для хранения текущего потока, когда вы берете блокировку, а затем распечатать ее, если кто-то другой пытается ее использовать.

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;
    }
}
person dac2009    schedule 04.12.2011

Некрасиво, но работает.

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);
    }
}
person petertc    schedule 29.03.2018