web-dev-qa-db-ja.com

Sun.misc.Unsafe.parkでの待機(ネイティブメソッド)

私のアプリケーションの1つは、負荷の下で実行されている一定の期間の下でハングします。

"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)

ハングしたとき、jstackの出力でこれをよく見ます。

Spring @Asyncとマップ、同期マップとehcacheを頻繁に使用しています。

興味深いことに、これはアプリインスタンスの1つでのみ発生します。他の2つは完全に正常に動作しています。そのような場合に詳細を調べるために他に何を調査できますか?

私はこの投稿を見つけました https://stackoverflow.com/questions/23992787/parking-to-wait-for-0xd8cf0070-a-Java-util-concurrent-locks-abstractqueueds しかし、私の場合はあまり役に立ちません。

61
Konrad

unsafe.parkはthread.waitとほとんど同じですが、アーキテクチャ固有のコードを使用している点が異なります(そのため「安全でない」理由です)。 unsafeは公開されていませんが、Java内部ライブラリ内で使用され、アーキテクチャ固有のコードにより大幅な最適化のメリットが得られます。スレッドプーリングに多く使用されています。

したがって、あなたの質問に答えるために、スレッドがしているのは何かを待っているだけで、実際にはCPUを使用していません。元のスタックトレースがロックを使用していることを示していることを考えると、あなたのケースではデッドロックが起こっていると思います。

はい、私はあなたがすでにこの問題をほぼ確実に解決していることを知っています。ただし、誰かがSun.misc.unsafe.parkをグーグルで検索した場合、あなたはトップの結果の1つになります。質問に答えることで、他の人がすべてのCPUを使用しているように見えるこのメソッドが何であるかを理解しようとするのに役立つと思います。

158
dsollen

スタックトレースから、ThreadPoolExecutor> Workerスレッドが開始され、BlockingQueue(DelayedWorkQueue)でタスクを選択して実行できるようになるまで待機していることが明らかです。したがって、このスレッドは、発行者スレッドからのシグナル。

6
Yoga Gowda

同様の問題があり、以前の回答(ありがとう!)に従って、ThreadPoolExecutorのターミナゾンを正しく処理する方法を検索して見つけることができました。

私の場合、それは同様のブロックされたスレッドの私の漸進的な増加を修正するだけです:

  • Finally節でExecutorService::awaitTermination(x, TimeUnit)ExecutorService::shutdownNow()(必要な場合)を使用しました。
  • 詳細については、次のコマンドを使用してスレッドカウントを検出し、ロックされたスレッドを一覧表示しました。

    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

1
boly38