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

StackOverflow https://stackoverflow.com/questions/50561

Вопрос

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

2- Позвонив по телефону holdsLock(Object o) способ.Это вернет логическое значение.

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

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

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

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

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

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);
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top