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




Вы можете только определить, имеет ли текущий поток нормальную блокировку (Thread.holdsLock(Object)). Вы не можете получить ссылку на поток с блокировкой без собственного кода.
Однако, если вы делаете что-нибудь сложное с потоками, вы, вероятно, захотите ознакомиться с пакетами java.util.concurrent. ReentrantLock позволяет вам получить своего владельца (но это защищенный метод, поэтому вам придется его расширить). В зависимости от вашего приложения вполне может оказаться, что, используя пакеты параллелизма, вы обнаружите, что вам все-таки не нужно получать владельца блокировки.
Существуют непрограммные методы поиска владельцев блокировок, такие как сигнализация JVM о выдаче дампа потока в stderr, которые полезны для определения причины взаимоблокировок.
Запустите jconsole. Он включен в Java SDK и запускается из командной строки. Я не уверен, какую ОС вы используете, но в Windows вы можете просто передать ей PID процесса Java. Это должно помочь вам найти нить, которая вызывает проблему. Или вы можете использовать коммерческий профилировщик, такой как YourKit, или любое количество других профилировщиков.
Начиная с версии 1.6, вы можете использовать JMX для выполнения всевозможных интересных вещей, включая поиск заблокированных блокировок. Вы не можете получить фактический объект, но вы получите хеш-значение класса и идентификатора (которое не является уникальным).
В 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
Вы можете добраться до замков, удерживаемых потоками с отражением. Это работает только с java 1.6.
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] ti = bean.getThreadInfo(bean.getAllThreadIds(), true, true);
На каждом из этих объектов ThreadInfo есть объекты LockInfo, которые вы можете использовать с помощью identityHashCode для сравнения с рассматриваемой блокировкой.
Вы можете использовать переменную, чтобы удерживать текущий поток, когда вы берете блокировку, а затем распечатывать ее, если кто-то пытается ее использовать.
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;
}
}
Вы можете проверить блокировку конкретного объекта, вызвав метод wait() или notify() для этого объекта. Если объект не удерживает блокировку, он выбрасывает llegalMonitorStateException.
2- Вызов метода holdsLock(Object o). Это вернет логическое значение.
если это блокировка с повторным входом, вы можете проверить, удерживается ли он текущим потоком
final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();
Уродливо, но работает.
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);
}
}
Измените заголовок и сообщение, указав, что вы имеете в виду Java. Тег не должен быть единственным местом, где размещается важная информация, относящаяся к вопросу.