并发主题

线程死锁研究之三

上页

通过前面threaddump输出,Account的线程死锁输出如下:

2012-10-16 13:37:03
Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.10-b01-428 mixed mode):

"DestroyJavaVM" prio=5 tid=7f9712001000 nid=0x110247000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE

"Thread-21" prio=5 tid=7f9712944000 nid=0x118d76000 waiting for monitor entry [118d75000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366f58> (a threads.deadlock.Account)
- locked <7f3366ee0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-20" prio=5 tid=7f971216c000 nid=0x118c73000 waiting for monitor entry [118c72000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e98> (a threads.deadlock.Account)
- locked <7f3366f58> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-19" prio=5 tid=7f9712943800 nid=0x118b70000 waiting for monitor entry [118b6f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366f40> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-18" prio=5 tid=7f9712942800 nid=0x118a6d000 waiting for monitor entry [118a6c000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366f40> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-17" prio=5 tid=7f9712942000 nid=0x11896a000 waiting for monitor entry [118969000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366ec8> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-16" prio=5 tid=7f9712941000 nid=0x118867000 waiting for monitor entry [118866000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366ec8> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-15" prio=5 tid=7f9712940800 nid=0x118764000 waiting for monitor entry [118763000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366ef8> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-14" prio=5 tid=7f971293f800 nid=0x118661000 waiting for monitor entry [118660000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366f28> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-13" prio=5 tid=7f97129ae000 nid=0x11855e000 waiting for monitor entry [11855d000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366eb0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-12" prio=5 tid=7f97129ad000 nid=0x11845b000 waiting for monitor entry [11845a000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366f40> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-11" prio=5 tid=7f97129ac800 nid=0x118358000 waiting for monitor entry [118357000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366f58> (a threads.deadlock.Account)
- locked <7f3366eb0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-10" prio=5 tid=7f97129ab800 nid=0x118255000 waiting for monitor entry [118254000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366eb0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-9" prio=5 tid=7f97129ab000 nid=0x118152000 waiting for monitor entry [118151000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e98> (a threads.deadlock.Account)
- locked <7f3366ec8> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-8" prio=5 tid=7f97129aa000 nid=0x11804f000 waiting for monitor entry [11804e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366eb0> (a threads.deadlock.Account)
- locked <7f3366f28> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-7" prio=5 tid=7f97129a9800 nid=0x117f4c000 waiting for monitor entry [117f4b000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366eb0> (a threads.deadlock.Account)
- locked <7f3366e80> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-6" prio=5 tid=7f97129a8800 nid=0x117e49000 waiting for monitor entry [117e48000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366e80> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-5" prio=5 tid=7f97128a1800 nid=0x117d46000 waiting for monitor entry [117d45000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:81)
- waiting to lock <7f3366f28> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-4" prio=5 tid=7f97121af800 nid=0x117c43000 waiting for monitor entry [117c42000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e80> (a threads.deadlock.Account)
- locked <7f3366e98> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-3" prio=5 tid=7f97121ae800 nid=0x117b40000 waiting for monitor entry [117b3f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e80> (a threads.deadlock.Account)
- locked <7f3366ef8> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"Thread-2" prio=5 tid=7f971224a000 nid=0x117a3d000 waiting for monitor entry [117a3c000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366eb0> (a threads.deadlock.Account)
- locked <7f3366f40> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

"RMI TCP Accept-0" daemon prio=5 tid=7f97128fd800 nid=0x117837000 runnable [117836000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
- locked <7f32ee740> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:34)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:369)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:341)
at java.lang.Thread.run(Thread.java:680)

"Poller SunPKCS11-Darwin" daemon prio=1 tid=7f97128fd000 nid=0x117734000 waiting on condition [117733000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at sun.security.pkcs11.SunPKCS11$TokenPoller.run(SunPKCS11.java:692)
at java.lang.Thread.run(Thread.java:680)

"Low Memory Detector" daemon prio=5 tid=7f971209e000 nid=0x1173ec000 runnable [00000000]
java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=9 tid=7f971209d000 nid=0x1172e9000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=9 tid=7f971209c800 nid=0x1171e6000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=9 tid=7f971209b800 nid=0x1170e3000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE

"Surrogate Locker Thread (Concurrent GC)" daemon prio=5 tid=7f971209a800 nid=0x116fe0000 waiting on condition [00000000]
java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=7f971209a000 nid=0x116d1c000 in Object.wait() [116d1b000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f3001300> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <7f3001300> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=10 tid=7f9712099000 nid=0x116c19000 in Object.wait() [116c18000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <7f30011d8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <7f30011d8> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=9 tid=7f9712096800 nid=0x116b16000 runnable

"Gang worker#0 (Parallel GC Threads)" prio=9 tid=7f9712002800 nid=0x1135c7000 runnable

"Gang worker#1 (Parallel GC Threads)" prio=9 tid=7f9712003000 nid=0x1136ca000 runnable

"Concurrent Mark-Sweep GC Thread" prio=9 tid=7f971204d800 nid=0x116790000 runnable
"VM Periodic Task Thread" prio=10 tid=7f97122d4000 nid=0x11793a000 waiting on condition

"Exception Catcher Thread" prio=10 tid=7f9712001800 nid=0x1103ef000 runnable
JNI global references: 1037

Found one Java-level deadlock:
=============================
"Thread-21":
waiting to lock monitor 7f97118bd560 (object 7f3366f58, a threads.deadlock.Account),
which is held by "Thread-20"
"Thread-20":
waiting to lock monitor 7f97118bc108 (object 7f3366e98, a threads.deadlock.Account),
which is held by "Thread-4"
"Thread-4":
waiting to lock monitor 7f9711834360 (object 7f3366e80, a threads.deadlock.Account),
which is held by "Thread-7"
"Thread-7":
waiting to lock monitor 7f97118b9708 (object 7f3366eb0, a threads.deadlock.Account),
which is held by "Thread-11"
"Thread-11":
waiting to lock monitor 7f97118bd560 (object 7f3366f58, a threads.deadlock.Account),
which is held by "Thread-20"

Java stack information for the threads listed above:
===================================================
"Thread-21":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366f58> (a threads.deadlock.Account)
- locked <7f3366ee0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-20":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e98> (a threads.deadlock.Account)
- locked <7f3366f58> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-4":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e80> (a threads.deadlock.Account)
- locked <7f3366e98> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-7":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366eb0> (a threads.deadlock.Account)
- locked <7f3366e80> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-11":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366f58> (a threads.deadlock.Account)
- locked <7f3366eb0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

Found 1 deadlock.

Heap
par new generation total 19136K, used 11590K [7f3000000, 7f44c0000, 7f44c0000)
eden space 17024K, 68% used [7f3000000, 7f3b51ac0, 7f40a0000)
from space 2112K, 0% used [7f40a0000, 7f40a0000, 7f42b0000)
to space 2112K, 0% used [7f42b0000, 7f42b0000, 7f44c0000)
concurrent mark-sweep generation total 63872K, used 0K [7f44c0000, 7f8320000, 7fae00000)
concurrent-mark-sweep perm gen total 21248K, used 8268K [7fae00000, 7fc2c0000, 800000000)

threaddump有下面几个部分:

应用的所有线程的完整列表。
死锁线程列表
一个小的堆栈跟踪死锁线程
该应用程序的堆摘要

线程列表:

从列表中看出:包含了应用程序一大堆的线程,你可以大致分为两个。首先是后台线程。这些都是每个应用程序都有的,作为应用程序的程序员,通常并不需要担心。这些名称,如:"DestroyJavaVM的"低内存检测,终结,异常捕手主题和并发标记扫描GC线程。其次,就是我们的代码的一部分创建的线程了。这些通常一个thread名称和数字组成。例如:thread-3的thread-6和thread-20。

"Thread-20" prio=5 tid=7f971216c000 nid=0x118c73000 waiting for monitor entry [118c72000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:82)
- waiting to lock <7f3366e98> (a threads.deadlock.Account)
- locked <7f3366f58> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:58)

解释如下:

thread-20是线程的名称, PRIO= 5是线程的优先级。数字从1到10,其中1为最低,10为最高优先级。 TID =7f971216c000 线程ID。由Thread.getId调用返回的一个独特的号码。 NID=0x118c73000本地硬件线程ID。这映射到一个依赖于平台的线程ID。 等待监视锁实体[118c72000]

java.lang.Thread.State: BLOCKED (on object monitor)代表这个线程堵塞住了。

总结一下threaddump的线程死锁情况:

Found one Java-level deadlock:
=============================
"Thread-21":
waiting to lock monitor 7f97118bd560 (object 7f3366f58, a threads.deadlock.Account),
which is held by "Thread-20"
"Thread-20":
waiting to lock monitor 7f97118bc108 (object 7f3366e98, a threads.deadlock.Account),
which is held by "Thread-4"
"Thread-4":
waiting to lock monitor 7f9711834360 (object 7f3366e80, a threads.deadlock.Account),
which is held by "Thread-7"
"Thread-7":
waiting to lock monitor 7f97118b9708 (object 7f3366eb0, a threads.deadlock.Account),
which is held by "Thread-11"
"Thread-11":
waiting to lock monitor 7f97118bd560 (object 7f3366f58, a threads.deadlock.Account),
which is held by "Thread-20"

五个线程都堵塞在了threads.deadlock.Account

这五个线程在依次等待对方:

死锁的堆栈情况:

Java stack information for the threads listed above:
===================================================
"Thread-21":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366f58> (a threads.deadlock.Account)
- locked <7f3366ee0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-20":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e98> (a threads.deadlock.Account)
- locked <7f3366f58> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-4":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366e80> (a threads.deadlock.Account)
- locked <7f3366e98> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-7":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366eb0> (a threads.deadlock.Account)
- locked <7f3366e80> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-11":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f3366f58> (a threads.deadlock.Account)
- locked <7f3366eb0> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)

 Thread-20在等待 Thread-11,而 Thread-11在等待 Thread-20

上面死锁情况简化图如下:

在上面的图中,我们删除对象ID的7f3366前缀,因此,现在对象7f3366f58是F58。从这个图中,你可以看到该对象F58被thread-20锁定在第59行,在等待对象E98上86行的锁。依次类推。

下面是86行代码:

 

可以得出的结论是,随机挑选两个帐户对象在59号线和86号线的顺序错误导致死锁。

 

 

下页

java多线程

Java同步或锁

Java性能调优