Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Вот пример в одном из моих веб-журналов.

Ответ 4

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

Ответ 5

В 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 дает вам информацию о том, является ли поток BLOCKED, WAITING и т.д., см. jdk api ThreadState

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

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