java 分析java死锁_Java死锁示例–如何分析死锁情况
java 分析java死鎖
死鎖是兩個線程或多個線程永遠被阻塞的編程情況,這種情況發生在至少兩個線程和兩個或更多資源的情況下。 在這里,我編寫了一個簡單的程序,它將導致死鎖情況,然后我們將看到如何對其進行分析。
Java死鎖示例
package com.journaldev.threads; public class ThreadDeadlock {public static void main(String[] args) throws InterruptedException {Object obj1 = new Object();Object obj2 = new Object();Object obj3 = new Object();Thread t1 = new Thread(new SyncThread(obj1, obj2), 't1');Thread t2 = new Thread(new SyncThread(obj2, obj3), 't2');Thread t3 = new Thread(new SyncThread(obj3, obj1), 't3');t1.start();Thread.sleep(5000);t2.start();Thread.sleep(5000);t3.start();} } class SyncThread implements Runnable{private Object obj1;private Object obj2;public SyncThread(Object o1, Object o2){this.obj1=o1;this.obj2=o2;}@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println(name + ' acquiring lock on '+obj1);synchronized (obj1) {System.out.println(name + ' acquired lock on '+obj1);work();System.out.println(name + ' acquiring lock on '+obj2);synchronized (obj2) {System.out.println(name + ' acquired lock on '+obj2);work();}System.out.println(name + ' released lock on '+obj2);}System.out.println(name + ' released lock on '+obj1);System.out.println(name + ' finished execution.');}private void work() {try {Thread.sleep(30000);} catch (InterruptedException e) {e.printStackTrace();}} }在上面的程序中,SyncThread實現了Runnable接口,并且通過使用同步塊一個接一個地獲取對每個對象的鎖定,從而對兩個對象起作用。
在main方法中,我為SyncThread運行了三個線程,并且每個線程之間都有一個共享資源。 線程以這樣的方式運行:它將能夠獲取第一個對象上的鎖,但是當它試圖獲取第二個對象上的鎖時,它將進入等待狀態,因為它已經被另一個線程鎖定了。 這對導致死鎖的線程之間的資源形成了循環依賴性。
當我執行上面的程序時,這里是生成的輸出,但是由于死鎖,程序永遠不會終止。
t1 acquiring lock on java.lang.Object@6d9dd520 t1 acquired lock on java.lang.Object@6d9dd520 t2 acquiring lock on java.lang.Object@22aed3a5 t2 acquired lock on java.lang.Object@22aed3a5 t3 acquiring lock on java.lang.Object@218c2661 t3 acquired lock on java.lang.Object@218c2661 t1 acquiring lock on java.lang.Object@22aed3a5 t2 acquiring lock on java.lang.Object@218c2661 t3 acquiring lock on java.lang.Object@6d9dd520在這里,我們可以從輸出中清楚地確定死鎖情況,但是在實際應用中,很難找到死鎖情況并對其進行調試。
分析死鎖
為了分析死鎖,我們需要查看應用程序的Java線程轉儲 ,在上一篇文章中,我解釋了如何使用VisualVM Profiler或jstack實用程序生成線程轉儲 。
這是上面程序的線程轉儲。
2012-12-27 19:08:34 Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode): 'Attach Listener' daemon prio=5 tid=0x00007fb0a2814000 nid=0x4007 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE 'DestroyJavaVM' prio=5 tid=0x00007fb0a2801000 nid=0x1703 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE 't3' prio=5 tid=0x00007fb0a204b000 nid=0x4d07 waiting for monitor entry [0x000000015d971000]java.lang.Thread.State: BLOCKED (on object monitor)at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f658> (a java.lang.Object)- locked <0x000000013df2f678> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722) 't2' prio=5 tid=0x00007fb0a1073000 nid=0x4207 waiting for monitor entry [0x000000015d209000]java.lang.Thread.State: BLOCKED (on object monitor)at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f678> (a java.lang.Object)- locked <0x000000013df2f668> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722) 't1' prio=5 tid=0x00007fb0a1072000 nid=0x5503 waiting for monitor entry [0x000000015d86e000]java.lang.Thread.State: BLOCKED (on object monitor)at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f668> (a java.lang.Object)- locked <0x000000013df2f658> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722) 'Service Thread' daemon prio=5 tid=0x00007fb0a1038000 nid=0x5303 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE 'C2 CompilerThread1' daemon prio=5 tid=0x00007fb0a1037000 nid=0x5203 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE 'C2 CompilerThread0' daemon prio=5 tid=0x00007fb0a1016000 nid=0x5103 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE 'Signal Dispatcher' daemon prio=5 tid=0x00007fb0a4003000 nid=0x5003 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE 'Finalizer' daemon prio=5 tid=0x00007fb0a4800000 nid=0x3f03 in Object.wait() [0x000000015d0c0000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)- locked <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177) 'Reference Handler' daemon prio=5 tid=0x00007fb0a4002000 nid=0x3e03 in Object.wait() [0x000000015cfbd000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000013de75320> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:503)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)- locked <0x000000013de75320> (a java.lang.ref.Reference$Lock) 'VM Thread' prio=5 tid=0x00007fb0a2049800 nid=0x3d03 runnable 'GC task thread#0 (ParallelGC)' prio=5 tid=0x00007fb0a300d800 nid=0x3503 runnable 'GC task thread#1 (ParallelGC)' prio=5 tid=0x00007fb0a2001800 nid=0x3603 runnable 'GC task thread#2 (ParallelGC)' prio=5 tid=0x00007fb0a2003800 nid=0x3703 runnable 'GC task thread#3 (ParallelGC)' prio=5 tid=0x00007fb0a2004000 nid=0x3803 runnable 'GC task thread#4 (ParallelGC)' prio=5 tid=0x00007fb0a2005000 nid=0x3903 runnable 'GC task thread#5 (ParallelGC)' prio=5 tid=0x00007fb0a2005800 nid=0x3a03 runnable 'GC task thread#6 (ParallelGC)' prio=5 tid=0x00007fb0a2006000 nid=0x3b03 runnable 'GC task thread#7 (ParallelGC)' prio=5 tid=0x00007fb0a2006800 nid=0x3c03 runnable 'VM Periodic Task Thread' prio=5 tid=0x00007fb0a1015000 nid=0x5403 waiting on condition JNI global references: 114 Found one Java-level deadlock: ============================= 't3':waiting to lock monitor 0x00007fb0a1074b08 (object 0x000000013df2f658, a java.lang.Object),which is held by 't1' 't1':waiting to lock monitor 0x00007fb0a1010f08 (object 0x000000013df2f668, a java.lang.Object),which is held by 't2' 't2':waiting to lock monitor 0x00007fb0a1012360 (object 0x000000013df2f678, a java.lang.Object),which is held by 't3' Java stack information for the threads listed above: =================================================== 't3':at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f658> (a java.lang.Object)- locked <0x000000013df2f678> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722) 't1':at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f668> (a java.lang.Object)- locked <0x000000013df2f658> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722) 't2':at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)- waiting to lock <0x000000013df2f678> (a java.lang.Object)- locked <0x000000013df2f668> (a java.lang.Object)at java.lang.Thread.run(Thread.java:722) Found 1 deadlock.線程轉儲輸出清楚地顯示了死鎖情況,并且所涉及的線程和資源導致了死鎖情況。
為了分析死鎖,我們需要尋找狀態為BLOCKED的線程,然后尋找等待鎖定的資源,每個資源都有一個唯一的ID,通過它我們可以找到哪個線程已經在對象上持有鎖。 例如,線程“ t3”正在等待鎖定0x000000013df2f658,但它已被線程“ t1”鎖定。
一旦分析了死鎖情況并找出了導致死鎖的線程,就需要進行代碼更改以避免死鎖情況。
避免死鎖
這些是我們可以避免大多數僵局情況的一些準則。
- 避免嵌套鎖 :這是導致死鎖的最常見原因,如果已經持有另一個資源,請避免鎖定另一個資源。 如果僅使用一個對象鎖,則幾乎不可能出現死鎖情況。 例如,這是不帶嵌套鎖的run()方法的另一種實現,并且程序成功運行且沒有死鎖情況。 public void run() {String name = Thread.currentThread().getName();System.out.println(name + ' acquiring lock on ' + obj1);synchronized (obj1) {System.out.println(name + ' acquired lock on ' + obj1);work();}System.out.println(name + ' released lock on ' + obj1);System.out.println(name + ' acquiring lock on ' + obj2);synchronized (obj2) {System.out.println(name + ' acquired lock on ' + obj2);work();}System.out.println(name + ' released lock on ' + obj2);System.out.println(name + ' finished execution.');}
- 僅鎖定所需條件 :您應該僅對必須處理的資源獲取鎖定,例如,在上述程序中,我正在鎖定完整的Object資源,但是如果我們僅對其中一個字段感興趣,則應該僅鎖定該對象具體字段不完整的對象。
- 避免無限期地等待 :如果兩個線程正在使用線程連接無限期地等待彼此完成,則可能會陷入死鎖。 如果您的線程必須等待另一個線程完成,則始終最好使用join并在等待線程完成的最長時間內使用它。
參考: Java死鎖示例–如何從我們的JCG合作伙伴 Pankaj Kumar的Developer Recipes博客上分析死鎖情況 。
翻譯自: https://www.javacodegeeks.com/2013/01/java-deadlock-example-how-to-analyze-deadlock-situation.html
java 分析java死鎖
總結
以上是生活随笔為你收集整理的java 分析java死锁_Java死锁示例–如何分析死锁情况的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机视频怎么投屏到笔记本电脑播放手机中的
- 下一篇: Java Message System简