WARTEN bei sun.misc.Unsafe.park (native Methode)

80

Eine meiner Anwendungen hängt unter einer gewissen Zeit unter Last. Weiß jemand, was eine solche Ausgabe in jstack verursachen könnte:

"scheduler-5" prio=10 tid=0x00007f49481d0000 nid=0x2061 waiting on condition [0x00007f494e8d0000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000006ee117310> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1085)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)

Ich sehe dies oft in der jstack-Ausgabe, wenn sie hängt.

Ich benutze Spring @Async & Maps, synchronisierte Maps & Ehcache.

Interessant ist, dass dies nur auf einer der App-Instanzen geschieht. Zwei andere laufen einwandfrei. Was könnte ich sonst noch untersuchen, um in einem solchen Fall mehr Details zu erhalten?

Ich fand diesen Beitrag /programming/23992787/parking-to-wait-for-0xd8cf0070-a-java-util-concurrent-locks-abstractqueueds, aber er ist in meinem Fall nicht sehr nützlich.

Konrad
quelle
2
Das ist ein SchedeuledExecutorService, der waitingwahrscheinlich die meiste Zeit sein wird. Du solltest woanders suchen. Das Warten hier verbraucht keine CPU und würde keine weiteren Leistungsprobleme verursachen.
John Vint
Wenn ich ein Wettmann wäre, würde ich Ihre Speichernutzung und das Auftreten von GC untersuchen.
John Vint
OK danke. Ich habe die GC-Protokollierung aktiviert und werde sehen, was ich dort finden kann.
Konrad
1
@ JohnVint Wenn Sie ein Wettmann wären, was würden Sie in Bezug auf die Speichernutzung und das Auftreten von GC vermuten? Ich habe ein ähnliches Problem
user3607022
4
@ user3607022 GC Overhead limit reached. Dies ist ein klarer Hinweis darauf, dass Ihre App Speicherprobleme hat. Wenn Sie das sehen, bedeutet dies, dass die alte Generation ziemlich voll ist und nicht weiter GC-fähig ist.
John Vint

Antworten:

191

unsafe.park ist so ziemlich dasselbe wie thread.wait, außer dass es architekturspezifischen Code verwendet (daher der Grund, warum es "unsicher" ist). unsicher wird nicht öffentlich zugänglich gemacht, sondern in internen Java-Bibliotheken verwendet, in denen architekturspezifischer Code erhebliche Optimierungsvorteile bietet. Es wird häufig zum Thread-Pooling verwendet.

Um Ihre Frage zu beantworten, wartet der Thread nur auf etwas, er verwendet eigentlich keine CPU. In Anbetracht der Tatsache, dass Ihre ursprüngliche Stapelverfolgung zeigt, dass Sie eine Sperre verwenden, würde ich davon ausgehen, dass in Ihrem Fall ein Deadlock vorliegt.

Ja, ich weiß, dass Sie dieses Problem mit ziemlicher Sicherheit bereits gelöst haben. Sie sind jedoch eines der besten Ergebnisse, wenn jemand sun.misc.unsafe.park googelt. Ich denke, die Beantwortung der Frage kann anderen helfen, zu verstehen, was diese Methode ist, die anscheinend ihre gesamte CPU nutzt.

dsollen
quelle
19
Und es wird geparkt, weil dieser Thread Teil eines Thread-Pools für ein ExecutorServiceist und darauf wartet, dass eine Aufgabe über Methoden wie in die Arbeitswarteschlange gestellt wird ExecutorService.submit(...).
Harold L
9

Aus dem Stack-Trace geht hervor, dass der Thread ThreadPoolExecutor> Worker gestartet wurde und darauf wartet, dass die Aufgabe in der BlockingQueue (DelayedWorkQueue) verfügbar ist, um die Aufgabe auszuwählen und auszuführen. Dieser Thread befindet sich also nur im Status WAIT, solange a SIGNAL aus dem Publisher-Thread.

Yoga Gowda
quelle
3

Ich hatte ein ähnliches Problem und nach den vorherigen Antworten (danke!) Konnte ich suchen und finden, wie ich mit der ThreadPoolExecutor-Terminierung richtig umgehen kann.

In meinem Fall behebt das nur meine fortschreitende Zunahme ähnlicher blockierter Threads:

  • Ich habe ExecutorService::awaitTermination(x, TimeUnit)und ExecutorService::shutdownNow()(falls erforderlich) in meiner finally-Klausel verwendet.
  • Zur Information habe ich die folgenden Befehle verwendet, um die Anzahl der Threads zu ermitteln und gesperrte Threads aufzulisten:

    ps -u javaAppuser -L | wc -l

    jcmd `ps -C java -o pid =` Thread.print >> threadPrintDayA.log

    jcmd `ps -C java -o pid =` Thread.print >> threadPrintDayAPlusOne.log

    cat threadPrint * .log | grep "pool-" | wc -l

boly38
quelle