4 Stimmen

Äußerst ungewöhnliche Situation - Thread blockiert bei einer Sperre, die er gerade hält?

Dieses Java-Programm, an dem ich arbeite, scheint beim Starten zu hängen, also habe ich versucht, das Problem mit jconsole zu beheben. Es stellt sich heraus, dass es auf einen Aufruf einer Methode wartet, die als - deklariert ist.

synchronized void stopQuery()

Aber hier ist der verrückte Teil, die Sperre für die "synchronisierte" Methode wird bereits von dem Thread gehalten, der dafür blockiert ist. Ich habe einen Screenshot von JConsole nach der Ausführung der MXBean-Methode getThreadInfo() beigefügt.

Beachten Sie, dass lockOwnerId und threadId identisch sind! Wie ist das überhaupt möglich?

alt text

Bearbeiten:
Link zu einer der Stack Traces dieser Situation. Beachten Sie, dass es nach einem Blick auf den Stacktrace den Anschein haben könnte, dass sogar der Thread "org.eclipse.jdt.internal.ui.text.JavaReconciler" versucht, auf dasselbe DiskIndex-Objekt zuzugreifen, aber wenn Sie sich die Objektadresse ansehen, werden Sie feststellen, dass es sich in Wirklichkeit um ein anderes DiskIndex-Objekt handelt.

Bearbeiten 2:
Ein weiterer Link zu einem anderen Stacktrace, den ich erhalten habe, als ich dieses Problem reproduzierte. Es sollte hilfreich sein, die beiden zu vergleichen, um zu sehen, was gemeinsam ist.

0 Stimmen

Können Sie einen kompletten Thread-Dump erstellen (Strg-Break, Strg-Alt-\ oder "kill -3") und diesen posten?

2voto

Bob Cross Punkte 22071

Das sieht nach einer besonders unangenehmen Pattsituation aus. Es ist schwer zu sagen, ohne ein wenig mehr Informationen. Hier ist, was ich sehe, ohne den Code vor mir, though:

Mögliches Deadlock auf (oder zumindest Streit um) Objektreferenz 0x00002aace2276720 zwischen "Text Viewer Hover Presenter" und "Worker-3", während "Worker-3" die Sperre auf Referenz 0x00002aace2276ad0 hält.

Diese zweite Referenz scheint die Ursache für einen ganzen Haufen blockierter Threads zu sein (insbesondere "Worker-4", "Worker-1" und "Worker-0").

Mein Vorschlag wäre, ASTProvider.java Zeile 450 zu überprüfen (siehe die Stapelverfolgung für die ersten beiden, wo die verdächtige Objektsperre gehalten zu werden scheint, aber dann nicht scheinen, um über die wait() zu erhalten). Ich würde auch vorschlagen, dass Sie versuchen, die ausführbare Datei auf einem einzelnen Kern zu sperren (in der Annahme, dass es sich um ein Multicore-System handelt).

Das nächste Codestück, das einen Test wert zu sein scheint, ist SelectionListenerWithASTManager.java, Zeile 153 (wo die Referenz 0x00002aace2276ad0 gesperrt ist, wodurch die Workers blockiert werden).

Schließfächer von 0x00002aace2276720:

"Text Viewer Hover Presenter" daemon prio=10 tid=0x00002aad20166400 nid=0x51f4 in Object.wait() [0x000000004254c000..0x000000004254dd90]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00002aace2276720> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:485)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:450)
    - locked <0x00002aace2276720> (a java.lang.Object)
    at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.NLSStringHover.getHoverInfo(NLSStringHover.java:87)
    at org.eclipse.jdt.internal.ui.text.java.hover.AbstractJavaEditorTextHover.getHoverInfo2(AbstractJavaEditorTextHover.java:86)
    at org.eclipse.jdt.internal.ui.text.java.hover.BestMatchHover.getHoverInfo2(BestMatchHover.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverProxy.getHoverInfo2(JavaEditorTextHoverProxy.java:82)
    at org.eclipse.jface.text.TextViewerHoverManager$4.run(TextViewerHoverManager.java:166)

"Worker-3" prio=10 tid=0x00002aad132c3800 nid=0x5166 in Object.wait() [0x0000000042249000..0x000000004224ab10]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00002aace2276720> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:485)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:450)
    - locked <0x00002aace2276720> (a java.lang.Object)
    at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:129)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$PartListenerGroup.calculateASTandInform(SelectionListenerWithASTManager.java:168)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - locked <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

Blockiert bei 0x00002aace2276ad0

"Worker-4" prio=10 tid=0x00002aad132c4000 nid=0x5167 waiting for monitor entry [0x000000004234b000..0x000000004234bc90]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - waiting to lock <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

"Worker-1" prio=10 tid=0x00002aad12835800 nid=0x5164 waiting for monitor entry [0x0000000041a42000..0x0000000041a42a10]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - waiting to lock <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

"Worker-0" prio=10 tid=0x00002aad11a0ac00 nid=0x5146 waiting for monitor entry [0x0000000041941000..0x0000000041941d90]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager$3.run(SelectionListenerWithASTManager.java:153)
    - waiting to lock <0x00002aace2276ad0> (a java.lang.Object)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

0voto

Carl Seleborg Punkte 12935

Ist die Methode irgendwie rekursiv? Vielleicht verwenden Sie innerhalb der Methode ein Objekt, das genau diese Methode benötigt?

1 Stimmen

Ich glaube nicht, dass es so funktioniert, es ist nicht die Methode, die das Schloss hält, sondern der Faden...

0voto

pdeva Punkte 39515

Aber Sperren für synchronisierte Methoden sind reentrant, d.h. wenn ein Thread, der die Sperre für dieses Objekt hält, versucht, es erneut zu sperren, wird er immer erfolgreich sein.

0voto

Chris Kimpton Punkte 5438

Es könnte sich lohnen, ein Stückchen Code zur Erkennung von Deadlocks auszuprobieren - wie diese .

Die stopQuery-Sperre scheint nicht die Sperre zuvor in der Stack-Trace erworben haben, aber dann, dass Sperre scheint nicht irgendwo anders entweder erworben haben - seltsam...

"Worker-2" prio=10 tid=0x00002aad1da66400 nid=0x5165 waiting for monitor entry [0x0000000041b43000..0x0000000041b43b90]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.eclipse.jdt.internal.core.index.DiskIndex.stopQuery(DiskIndex.java)
    - waiting to lock <0x00002aacdfe83ea8> (a org.eclipse.jdt.internal.core.index.DiskIndex)
    at org.eclipse.jdt.internal.core.index.Index.stopQuery(Index.java:192)

Es gibt eine Wartezeit auf eine gehaltene Sperre in diesem Bit, aber das ist die Sperre freigegeben, bis es eine Benachrichtigung / Timeout bekommt:

"Text Viewer Hover Presenter" daemon prio=10 tid=0x00002aad20166400 nid=0x51f4 in Object.wait() [0x000000004254c000..0x000000004254dd90]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00002aace2276720> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:485)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.getAST(ASTProvider.java:450)
    - locked <0x00002aace2276720> (a java.lang.Object)
    at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.NLSStringHover.getHoverInfo(NLSStringHover.java:87)
    at org.eclipse.jdt.internal.ui.text.java.hover.AbstractJavaEditorTextHover.getHoverInfo2(AbstractJavaEditorTextHover.java:86)
    at org.eclipse.jdt.internal.ui.text.java.hover.BestMatchHover.getHoverInfo2(BestMatchHover.java:129)
    at org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverProxy.getHoverInfo2(JavaEditorTextHoverProxy.java:82)
    at org.eclipse.jface.text.TextViewerHoverManager$4.run(TextViewerHoverManager.java:166)

0 Stimmen

Ich habe einen Deadlock-Check in Jconsole durchgeführt und nichts gefunden.

0voto

Aaron Digulla Punkte 308693

Ist es möglich, dass DiskIndex.java keine Zeileninformationen hat? Meine Vermutung ist, dass Sie innerhalb der Methode hängen, wo es versucht, eine völlig andere Sperre zu erwerben, aber Sie können nicht sehen, dass, weil es keine Zeileninformationen in der Stack-Trace anzuzeigen.

0 Stimmen

Ich habe versucht, ein println in stopQuery() zu setzen. Der Aufruf wird nie eingegeben.

0 Stimmen

Okay. Ich sehe nicht, wo der Thread die Sperre in der Stapelverfolgung erwirbt. Ich schlage vor, dass du dir einen Dump aller Monitore besorgst und überprüfst, ob die Info, die du oben siehst, nicht wirklich "Thread versucht zu sperren" bedeutet. Auf den ersten Blick würde ich Ihnen zustimmen, aber offensichtlich liegen wir falsch, sonst würde es nicht hängen.

0 Stimmen

Ich verstehe Sie nicht. Wenn es heißt "blockiert", bedeutet dies, dass der Thread blockiert ist und darauf wartet, das Objekt zu sperren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X