어떤 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 개체 각각에는 문제의 잠금과 비교하기 위해 해당 개체에 대한 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);
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top