<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    John Jiang

    a cup of Java, cheers!
    https://github.com/johnshajiang/blog

       :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
      131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
    Java并發基礎實踐--死鎖
    本文是Java并發基礎實踐系列中的一篇,介紹了最簡單的死鎖場景,并使用jstack產生的thread dump來查找死鎖。(2013.12.29最后更新)

    1. 死鎖
    為了能夠維護線程的安全性,Java提供的鎖機制,但不恰當地使用鎖則可能產生死鎖。死鎖是并發編程中一個無法繞開的問題。只要在一個任務中使用了一個以上的鎖,那么就存在死鎖的風險。
    死鎖產生的直接原因非常簡單,即兩個線程在相互等待對方所執有的鎖。

    2. 鎖順序死鎖
    在死鎖場景中,最典型的就是鎖順序死鎖,代碼清單1就是一個很常見的示例。
    清單1
    public class DeadLock {

        
    private Object leftLock = new Object();
        
    private Object rightLock = new Object();

        
    public void leftRight() {
            
    synchronized (leftLock) {
                
    try {
                    TimeUnit.SECONDS.sleep(
    3);
                } 
    catch (InterruptedException e) {
                    e.printStackTrace();
                }

                
    synchronized (rightLock) {
                    System.out.println(
    "leftRight");
                }
            }
        }

        
    public void rightLeft() {
            
    synchronized (rightLock) {
                
    try {
                    TimeUnit.SECONDS.sleep(
    3);
                } 
    catch (InterruptedException e) {
                    e.printStackTrace();
                }

                
    synchronized (leftLock) {
                    System.out.println(
    "leftRight");
                }
            }
        }

        
    public static void main(String[] args) {
            
    final DeadLock deadLock = new DeadLock();

            Thread t1 
    = new Thread(new Runnable() {

                @Override
                
    public void run() {
                    deadLock.leftRight();
                }
            });

            Thread t2 
    = new Thread(new Runnable() {

                @Override
                
    public void run() {
                    deadLock.rightLeft();
                }
            });

            t1.start();
            t2.start();
        }
    }

    3. Thread Dump
    JDK提供了一組命令行工具,其中就包括jstack。通過jstack可以獲取當前正運行的Java進程的java stack和native stack信息。如果Java進程崩潰了,也可以通過它來獲取core file中的java stack和native stack信息,以方便我們定位問題。
    為了能夠使用jstack去輸出目標Java進程的thread dump,首先必須要弄清楚在執行清單1的程序時,該程序的進程號。JDK提供的另一個命令行工具jps可以獲取系統中所有Java進程的相關信息。
    在命令行窗口中執行命令jps,即可以得到清單2所示的結果
    清單2
    C:\Documents and Settings\Administrator>jps
    2848
    4552 DeadLock
    5256 Jps
    其中4552就是在筆者機器上執行程序DeadLock時所生成Java進程的進程號。
    然后再執行命令jstack 4552,在筆者的機器上就會得到清單3所示的結果
    清單3
    C:\Documents and Settings\Administrator>jstack 
    4552
    2013-12-29 18:45:41
    Full thread dump Java HotSpot(TM) Client VM (
    23.25-b01 mixed mode, sharing):

    "DestroyJavaVM" prio=6 tid=0x00878800 nid=0xd00 waiting on condition [0x00000000]
       java.lang.Thread.State: RUNNABLE

    "Thread-1" prio=6 tid=0x02b56c00 nid=0x14ec waiting for monitor entry [0x02fdf000]
       java.lang.Thread.State: BLOCKED (on object monitor)
            at concurrency.deadlock.DeadLock.rightLeft(DeadLock.java:
    33)
            - waiting to lock <0x22be6598> (a java.lang.Object)
            - locked <0x22be65a0> (a java.lang.Object)
            at concurrency.deadlock.DeadLock$
    2.run(DeadLock.java:53)
            at java.lang.Thread.run(Thread.java:
    724)

    "Thread-0" prio=6 tid=0x02b55c00 nid=0x354 waiting for monitor entry [0x02f8f000]
       java.lang.Thread.State: BLOCKED (on object monitor)
            at concurrency.deadlock.DeadLock.leftRight(DeadLock.java:
    19)
            - waiting to lock <0x22be65a0> (a java.lang.Object)
            - locked <0x22be6598> (a java.lang.Object)
            at concurrency.deadlock.DeadLock$
    1.run(DeadLock.java:45)
            at java.lang.Thread.run(Thread.java:
    724)

    "Service Thread" daemon prio=6 tid=0x02b34800 nid=0x133c runnable [0x00000000]
       java.lang.Thread.State: RUNNABLE

    "C1 CompilerThread0" daemon prio=10 tid=0x02b13800 nid=0x10fc waiting on condition [0x00000000]
       java.lang.Thread.State: RUNNABLE

    "Attach Listener" daemon prio=10 tid=0x02b11c00 nid=0x1424 waiting on condition [0x00000000]
       java.lang.Thread.State: RUNNABLE

    "Signal Dispatcher" daemon prio=10 tid=0x02b10800 nid=0x1100 runnable [0x00000000]
       java.lang.Thread.State: RUNNABLE

    "Finalizer" daemon prio=8 tid=0x02af4c00 nid=0x1238 in Object.wait() [0x02daf000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x22b60fb8> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:
    135)
            - locked <0x22b60fb8> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:
    151)
            at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:
    189)

    "Reference Handler" daemon prio=10 tid=0x02af0000 nid=0x12e8 in Object.wait() [0x02d5f000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x22b60da0> (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 <0x22b60da0> (a java.lang.ref.Reference$Lock)

    "VM Thread" prio=10 tid=0x02aee400 nid=0x129c runnable

    "VM Periodic Task Thread" prio=10 tid=0x02b48000 nid=0x89c waiting on condition

    JNI global references: 
    117


    Found one Java-level deadlock:
    =============================
    "Thread-1":
      waiting to lock monitor 0x02af4a3c (object 0x22be6598
    , a java.lang.Object),
      which is held by 
    "Thread-0"
    "Thread-0":
      waiting to lock monitor 0x02af310c (object 0x22be65a0
    , a java.lang.Object),
      which is held by 
    "Thread-1"

    Java stack information for the threads listed above:
    ===================================================
    "Thread-1":
            at concurrency.deadlock.DeadLock.rightLeft(DeadLock.java:
    33)
            - waiting to lock <0x22be6598> (a java.lang.Object)
            - locked <0x22be65a0> (a java.lang.Object)
            at concurrency.deadlock.DeadLock$
    2.run(DeadLock.java:53)
            at java.lang.Thread.run(Thread.java:
    724)
    "Thread-0":
            at concurrency.deadlock.DeadLock.leftRight(DeadLock.java:
    19)
            - waiting to lock <0x22be65a0> (a java.lang.Object)
            - locked <0x22be6598> (a java.lang.Object)
            at concurrency.deadlock.DeadLock$
    1.run(DeadLock.java:45)
            at java.lang.Thread.run(Thread.java:
    724)

    Found 
    1 deadlock.
    在上述輸出中,我們可以很明確地看到一個死鎖
    "Thread-1":
      waiting to lock monitor 0x02af4a3c (object 0x22be6598
    , a java.lang.Object),
      which is held by 
    "Thread-0"
    "Thread-0":
      waiting to lock monitor 0x02af310c (object 0x22be65a0
    , a java.lang.Object),
      which is held by 
    "Thread-1"
    并且它還標明了程序是在哪個地方時發現了上述死鎖
    "Thread-1":
            at concurrency.deadlock.DeadLock.rightLeft(DeadLock.java:
    33)
            - waiting to lock <0x22be6598> (a java.lang.Object)
            - locked <0x22be65a0> (a java.lang.Object)
            at concurrency.deadlock.DeadLock$
    2.run(DeadLock.java:53)
            at java.lang.Thread.run(Thread.java:
    724)
    "Thread-0":
            at concurrency.deadlock.DeadLock.leftRight(DeadLock.java:
    19)
            - waiting to lock <0x22be65a0> (a java.lang.Object)
            - locked <0x22be6598> (a java.lang.Object)
            at concurrency.deadlock.DeadLock$
    1.run(DeadLock.java:45)
            at java.lang.Thread.run(Thread.java:
    724)

    4. 小結
    死鎖產生的直接原因非常簡單,即兩個線程在相互等待對方所執有的鎖。鎖順序死鎖是其中最經典的場景,此外還有動態的鎖順序死鎖。雖然表現形式有所不同,但本質上都是兩個線程在以不同的順序來獲取相同鎖時,發生了死鎖問題。
    使用thread dump可以幫助我們分析死鎖產生的原因。除了直接使用jstack命令來獲取thread dump輸出以外,JDK還提供了jvisualvm工具,它能以可視化的方式展示Java程序的進程號并導出thread dump。
    posted on 2013-12-29 20:19 John Jiang 閱讀(12275) 評論(1)  編輯  收藏 所屬分類: JavaSEJavaConcurrency原創Java并發基礎實踐

    評論

    # re: Java并發基礎實踐--死鎖(原) 2014-01-01 12:17 私人訂制
    好東西學習了  回復  更多評論
      

    主站蜘蛛池模板: 毛片在线全部免费观看| 国产特级淫片免费看| 婷婷综合缴情亚洲狠狠尤物| 亚洲春色在线观看| 在线观看永久免费| 亚洲视频一区在线观看| 亚洲精品免费观看| 久久综合亚洲色一区二区三区 | 免费欧洲毛片A级视频无风险| 亚洲国产成人精品无码一区二区 | 中文亚洲成a人片在线观看| 一级毛片免费视频网站| WWW亚洲色大成网络.COM| 国产亚洲精品高清在线| 亚洲国产成人一区二区三区| 亚洲中文字幕无码爆乳| 青青青青青青久久久免费观看| 亚洲欧美自偷自拍另类视| 暖暖免费高清日本一区二区三区| 亚洲а∨精品天堂在线| 国产zzjjzzjj视频全免费| 九九久久国产精品免费热6| 国产亚洲大尺度无码无码专线| a级大片免费观看| 亚洲狠狠ady亚洲精品大秀| 国产精品无码免费播放| 日韩亚洲人成在线综合| 亚洲精品国产精品国自产观看| 99re8这里有精品热视频免费| 亚洲天堂视频在线观看| 国产在线国偷精品产拍免费| 久久精品国产亚洲AV电影网| 亚洲免费日韩无码系列| 久久国产高潮流白浆免费观看| 亚洲综合久久一本伊伊区| 亚洲色婷婷综合开心网| 精品熟女少妇a∨免费久久| 亚洲中文字幕一二三四区| 色综合久久精品亚洲国产| 亚洲午夜激情视频| 中国一级特黄高清免费的大片中国一级黄色片 |