Java知多少(64)線程死結

來源:互聯網
上載者:User

標籤:

需要避免的與多任務處理有關的特殊錯誤類型是死結(deadlock)。死結發生在當兩個線程對一對同步對象有循環相依性關係時。例如,假定一個線程進入了對象X的管程而另一個線程進入了對象Y的管程。如果X的線程試圖調用Y的同步方法,它將像預料的一樣被鎖定。而Y的線程同樣希望調用X的一些同步方法,線程永遠等待,因為為到達X,必須釋放自己的Y的鎖定以使第一個線程可以完成。死結是很難調試的錯誤,因為:

  • 通常,它極少發生,只有到兩線程的時間段剛好符合時才能發生。
  • 它可能包含多於兩個的線程和同步對象(也就是說,死結在比剛講述的例子有更多複雜的事件序列的時候可以發生)。


為充分理解死結,觀察它的行為是很有用的。下面的例子產生了兩個類,A和B,分別有foo( )和bar( )方法。這兩種方法在調用其他類的方法前有一個短暫的停頓。主類,名為Deadlock,建立了A和B的執行個體,然後啟動第二個線程去設定死結環境。foo( )和bar( )方法使用sleep( )強迫死結現象發生。

 1 // An example of deadlock. 2 class A { 3     synchronized void foo(B b) { 4         String name = Thread.currentThread().getName(); 5         System.out.println(name + " entered A.foo"); 6         try { 7             Thread.sleep(1000); 8         } catch(Exception e) { 9             System.out.println("A Interrupted");10         }11         System.out.println(name + " trying to call B.last()");12         b.last();13     }14     synchronized void last() {15         System.out.println("Inside A.last");16     }17 }18 class B {19     synchronized void bar(A a) {20         String name = Thread.currentThread().getName();21         System.out.println(name + " entered B.bar");22         try {23             Thread.sleep(1000);24         } catch(Exception e) {25             System.out.println("B Interrupted");26         }27         System.out.println(name + " trying to call A.last()");28         a.last();29     }30     synchronized void last() {31         System.out.println("Inside A.last");32     }33 }34 class Deadlock implements Runnable {35     A a = new A();36     B b = new B();37     Deadlock() {38         Thread.currentThread().setName("MainThread");39         Thread t = new Thread(this, "RacingThread");40         t.start();41         a.foo(b); // get lock on a in this thread.42         System.out.println("Back in main thread");43     }44     public void run() {45         b.bar(a); // get lock on b in other thread.46         System.out.println("Back in other thread");47     }48     public static void main(String args[]) {49         new Deadlock();50     }51 }

運行程式後,輸出如下:

MainThread entered A.foo
RacingThread entered B.bar
MainThread trying to call B.last()
RacingThread trying to call A.last()

因為程式死結,你需要按CTRL-C來結束程式。在PC機上按CTRL-BREAK(或在Solaris下按CTRL-\)你可以看到全線程和管程緩衝堆。你會看到RacingThread在等待管程a時佔用管程b,同時,MainThread佔用a等待b。該程式永遠都不會結束。像該例闡明的,你的多線程程式經常被鎖定,死結是你首先應檢查的問題。

系列文章:

Java知多少(上)

Java知多少(39)interface介面

Java知多少(40)介面和抽象類別的區別

Java知多少(41)泛型詳解

Java知多少(42)泛型萬用字元和型別參數的範圍

Java知多少(43)異常處理基礎

Java知多少(44)異常類型

Java知多少(45)未被捕獲的異常

Java知多少(46)try和catch的使用

Java知多少(47)多重catch語句的使用

Java知多少(48)try語句的嵌套

Java知多少(49)throw:異常的拋出

Java知多少(50)Java throws子句

Java知多少(51)finally

Java知多少(52)內建異常

Java知多少(53)使用Java建立自己的異常子類

Java知多少(54)斷言詳解

Java知多少(55)線程

Java知多少(56)執行緒模式Java知多少(57)主線程Java知多少(58)線程Runnable介面和Thread類詳解Java知多少(59)建立多線程Java知多少(60)isAlive()和join()的使用Java知多少(61)線程優先順序Java知多少(62)線程同步Java知多少(63)線程間通訊

Java知多少(64)線程死結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.