確かに可能です。実行時にチェックすることもできます!
最初のステップは、スレッドダンプを取得することです。ここに3つの方法があります。
- VisualVMでプロセスを開き、[スレッド]タブに移動すると、この種のデッドロックを検出するかどうかがわかります。その後、スレッドダンプ(すぐそこにボタンがあります)を実行できます。これにより、各スレッドが何をしているのか、所有するロック、および取得しようとしているロック(もしあれば)があります。
- LinuxまたはMacでは、発行することでスタックを取得できます
kill -3 <pid>
, 、 どこ <pid>
あなたのJava Process 'IDです。同じスレッドダンプをstderrにダンプします。そのスレッドダンプの下部には、検出するデッドロックの要約も含まれています。 Windowsでこれを行う方法がわかりません。
- 呼び出すこともできます
jstack <pid>
, 、スレッドダンプをstdoutに印刷します( jstack
s stdout、元のJavaプロセスではなく ')。
デッドロックして実行したサンプルプログラムを作成しました(参照してください 私の要点)。スレッドダンプの関連セクションは次のとおりです。
Found one Java-level deadlock:
=============================
"Thread-2":
waiting for ownable synchronizer 7f42b0f38, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
which is held by "Thread-1"
"Thread-1":
waiting for ownable synchronizer 7f42ba170, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
which is held by "Thread-2"
関連するスレッド状態は次のとおりです。
"Thread-2" prio=5 tid=7fc01c911000 nid=0x113d18000 waiting on condition [113d17000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <7f30c3528> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
at Locky$Boomer.run(Locky.java:22)
at java.lang.Thread.run(Thread.java:680)
Locked ownable synchronizers:
- <7f30c3558> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"Thread-1" prio=5 tid=7fc01d06c800 nid=0x113c15000 waiting on condition [113c14000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <7f30c3558> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
at Locky$Boomer.run(Locky.java:22)
at java.lang.Thread.run(Thread.java:680)
Locked ownable synchronizers:
- <7f30c3528> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
これは機能しません 全て デッドロック。たとえば、外部リソースを待つためのデッドロックは捕まりません。しかし、それはキャッチされます Lock
- ベースのデッドロックなど synchronized
- ベースのもの。