어떤 Java 스레드가 잠금을 보유하고 있는지 프로그래밍 방식으로 확인
-
09-06-2019 - |
문제
주어진 객체의 잠금을 유지하고 있는 스레드의 이름을 프로그래밍 방식으로 런타임에 확인하는 것이 가능합니까?
해결책
현재 스레드가 일반 잠금을 보유하고 있는지 여부만 알 수 있습니다(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 개체 각각에는 문제의 잠금과 비교하기 위해 해당 개체에 대한 IdentityHashCode를 사용할 수 있는 LockInfo 개체가 있습니다.
1.6부터 JMX를 사용하여 보류된 잠금 찾기를 포함한 모든 종류의 흥미로운 작업을 수행할 수 있습니다.실제 객체를 얻을 수는 없지만 클래스 및 ID 해시 값(고유하지 않음)은 얻을 수 있습니다.
달리다 j콘솔.이는 Java SDK에 포함되어 있으며 명령줄에서 실행됩니다.어떤 OS를 사용하고 있는지 잘 모르겠지만 Windows에서는 Java 프로세스의 PID를 전달할 수 있습니다.문제를 일으키는 스레드를 찾는 데 도움이 됩니다.또는 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는 스레드가 차단되었는지, 대기 중인지 등에 대한 정보를 제공합니다. jdk API ThreadState
호출하여 특정 객체에 대한 잠금을 확인할 수 있습니다. 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);
}
}