Frage

Ist es zur Laufzeit möglich, den Namen des Threads, der die Sperre eines bestimmten Objekts hält, programmgesteuert zu überprüfen?

War es hilfreich?

Lösung

Sie können nur feststellen, ob der aktuelle Thread eine normale Sperre hält (Thread.holdsLock(Object)).Ohne nativen Code können Sie keinen Verweis auf den Thread erhalten, der die Sperre hat.

Wenn Sie jedoch etwas Kompliziertes mit Threading machen, möchten Sie sich wahrscheinlich mit den java.util.concurrent-Paketen vertraut machen.Der ReentrantLock ermöglicht es Ihnen, den Besitzer abzurufen (aber es ist eine geschützte Methode, daher müssten Sie diese erweitern).Abhängig von Ihrer Anwendung kann es durchaus sein, dass Sie durch die Verwendung der Parallelitätspakete feststellen, dass Sie den Besitzer der Sperre doch nicht ermitteln müssen.

Es gibt nicht-programmgesteuerte Methoden zum Auffinden der Sperreneigentümer, z. B. das Signalisieren der JVM, einen Thread-Dump an stderr auszugeben, die nützlich sind, um die Ursache von Deadlocks zu ermitteln.

Andere Tipps

An die von Fäden gehaltenen Schlösser kommt man mit Reflexion heran.Dies funktioniert nur mit Java 1.6.

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

Auf jedem dieser ThreadInfo-Objekte gibt es LockInfo-Objekte, deren IdentityHashCode Sie zum Vergleich mit der betreffenden Sperre verwenden können.

Ab 1.6 können Sie mit JMX alle möglichen interessanten Dinge tun, einschließlich der Suche nach gehaltenen Sperren.Sie können nicht das eigentliche Objekt abrufen, aber Sie erhalten den Klassen- und Identitäts-Hashwert (der nicht eindeutig ist).

In einem meiner Weblogs gibt es ein Beispiel.

Laufen jconsole.Es ist im Java SDK enthalten und wird über die Befehlszeile ausgeführt.Ich bin nicht sicher, welches Betriebssystem Sie verwenden, aber unter Windows können Sie ihm einfach die PID des Java-Prozesses übergeben.Es sollte Ihnen helfen, den Thread zu finden, der das Problem verursacht.Oder Sie können einen kommerziellen Profiler wie YourKit oder eine beliebige Anzahl anderer Profiler verwenden.

In 1.5 können Sie alle Threads finden und den Status jedes einzelnen abrufen, z. B. so:

    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 gibt Ihnen Informationen darüber, ob der Thread blockiert ist, wartet usw., siehe JDK-API ThreadState

Sie können die Sperre für das jeweilige Objekt durch einen Anruf überprüfen wait() oder notify() Methode für dieses Objekt.Wenn das Objekt die Sperre nicht hält, wird es ausgelöst llegalMonitorStateException .

2- Per Anruf holdsLock(Object o) Methode.Dadurch wird der boolesche Wert zurückgegeben.

wenn ja Wiedereintrittssperre Sie können überprüfen, ob es vom aktuellen Thread gehalten wird

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

Sie können eine Variable verwenden, um den aktuellen Thread zu speichern, wenn Sie die Sperre aufheben, und ihn dann auszugeben, wenn jemand anderes versucht, ihn zu verwenden.

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

Hässlich, aber funktioniert.

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);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top