分析Java死锁:分析jstack日志(九)
ferOperation.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)
From the previous section, we know that Thread-20 is waiting, via a circuitous route, forThread-11 and Thread-11 is waiting for Thread-20. This is our deadlock.
The next step is to tie this deadlock up to lines of code using the thread stack trace above and I’ve simplified this in the diagram below.
In the above diagram I've removed the 7f3366 prefix from the object ids for clarity; hence, object7f3366f58 is now f58. From this diagram, you can see that objectf58 is locked by Thread-20 on line 59 and is waiting for a lock on objecte98 on line 86. Following the arrows down, you can see that Thread-7 is waiting for a lock oneb0 on line 86, which in turn is locked by Thread-11 on line 59.Thread-11 is waiting for a lock on f58 on line 86, which, looping back up, is locked on line 58 byThread-20
So, where are these lines of code The following shows line 59:
...and this is line 86:
Everyone gets surprises sometimes and the stack trace above surprised me. I was expecting the locks to be on lines 85 and 86; however, they were on 59 and 86. Since line 59 doesn’t contain asynchronized keyword, I’m guessing that the compiler has done some optimisation on thetransfer(...) method’s first synchronized keyword.
The conclusion that can be drawn from this is that the code, which randomly picks twoAccount objects from a list, is locking them in the wrong order on lines 59 and 86. So what’s the fix More on that next time; however, there’s one final point to note, which is that the make up of a deadlock may not be the same every time you generate a thread dump on a program. After running the DeadlockDemo program again and usingkill -3 PID to get hold of another thread dump, I obtained these results:
Found one Java-level deadlock:
=============================
"Thread-20":
waiting to lock monitor 7fdc7c802508 (object 7f311a530, a threads.deadlock.Account),
which is held by "Thread-3"
"Thread-3":
waiting to lock monitor 7fdc7a83d008 (object 7f311a518, a threads.deadlock.Account),
which is held by "Thread-11"
"Thread-11":
waiting to lock monitor 7fdc7c802508 (object 7f311a530, a threads.deadlock.Account),
which is held by "Thread-3"
Java stack information for the threads listed above:
===================================================
"Thread-20":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:86)
- waiting to lock <7f311a530> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-3":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:87)
- waiting to lock <7f311a518> (a threads.deadlock.Account)
- locked <7f311a530> (a threads.deadlock.Account)
at threads.deadlock.DeadlockDemo$BadTransferOperation.run(DeadlockDemo.java:59)
"Thread-11":
at threads.deadlock.DeadlockDemo$BadTransferOperation.transfer(DeadlockDemo.java:87)
- waiting to lock <7f311a530> (a threads.deadlock.Account)
- locked <7f311a518> (a threads.deadlock.Account)