什么是死鎖?如何避免死鎖? 以及實現線程死鎖才程序


死鎖是什么

所謂死鎖:是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。由於資源占用是互斥的,當某個進程提出申請資源后,使得有關進程在無外力協助下,永遠分配不到必需的資源而無法繼續運行,這就產生了一種特殊現象死鎖。

死鎖的必要條件

雖然進程在運行過程中,可能發生死鎖,但死鎖的發生也必須具備一定的條件,死鎖的發生必須具備以下四個必要條件

1)互斥條件:指進程對所分配到的資源進行排它性使用,即在一段時間內某資源只由一個進程占用。如果此時還有其它進程請求資源,則請求者只能等待,直至占有資源的進程用畢釋放。

2)請求和保持條件:指進程已經保持至少一個資源,但又提出了新的資源請求,而該資源已被其它進程占有,此時請求進程阻塞,但又對自己已獲得的其它資源保持不放。

3)不剝奪條件:指進程已獲得的資源,在未使用完之前,不能被剝奪,只能在使用完時由自己釋放。

4)環路等待條件:指在發生死鎖時,必然存在一個進程——資源的環形鏈,即進程集合{P0P1P2···Pn}中的P0正在等待一個P1占用的資源;P1正在等待P2占用的資源,……Pn正在等待已被P0占用的資源。

在系統中已經出現死鎖后,應該及時檢測到死鎖的發生,並采取適當的措施來解除死鎖。目前處理死鎖的方法可歸結為以下四種:

預防死鎖

  這是一種較簡單和直觀的事先預防的方法。方法是通過設置某些限制條件,去破壞產生死鎖的四個必要條件中的一個或者幾個,來預防發生死鎖。預防死鎖是一種較易實現的方法,已被廣泛使用。但是由於所施加的限制條件往往太嚴格,可能會導致系統資源利用率和系統吞吐量降低。

 避免死鎖

  該方法同樣是屬於事先預防的策略,但它並不須事先采取各種限制措施去破壞產生死鎖的的四個必要條件,而是在資源的動態分配過程中,用某種方法去防止系統進入不安全狀態,從而避免發生死鎖。(安全狀態、銀行家算法)

檢測死鎖

  這種方法並不須事先采取任何限制性措施,也不必檢查系統是否已經進入不安全區,此方法允許系統在運行過程中發生死鎖。但可通過系統所設置的檢測機構,及時地檢測出死鎖的發生,並精確地確定與死鎖有關的進程和資源,然后采取適當措施,從系統中將已發生的死鎖清除掉。(死鎖定理化簡資源分配圖)

解除死鎖

  這是與檢測死鎖相配套的一種措施。當檢測到系統中已發生死鎖時,須將進程從死鎖狀態中解脫出來。常用的實施方法是撤銷或掛起一些進程,以便回收一些資源,再將這些資源分配給已處於阻塞狀態的進程,使之轉為就緒狀態,以繼續運行。死鎖的檢測和解除措施,有可能使系統獲得較好的資源利用率和吞吐量,但在實現上難度也最大。(資源剝奪法,撤銷進程法,進程回退法)

用兩個線程請求被對方占用的資源,實現線程死鎖

 

[java] view plain copy
  1. /** 
  2.  * 用兩個線程請求被對方占用的資源,實現線程死鎖 
  3.  */  
  4. public class DeadLockThread implements Runnable {  
  5.     private static final Object objectA = new Object();  
  6.     private static final Object objectB = new Object();  
  7.     private boolean flag;  
  8.   
  9.     @Override  
  10.     public void run() {  
  11.         String threadName = Thread.currentThread().getName();  
  12.         System.out.println("當前線程 為:"   
  13.         + threadName + "\tflag = " + flag);  
  14.         if (flag) {  
  15.             synchronized (objectA) {  
  16.                 try {  
  17.                     Thread.sleep(1000);  
  18.                 } catch (InterruptedException e) {  
  19.                     e.printStackTrace();  
  20.                 }  
  21.                 System.out.println(threadName   
  22.                         + "已進入同步代碼塊objectA,准備進入objectB");  
  23.                 synchronized (objectB) {  
  24.                     System.out.println(threadName   
  25.                             + "已經進入同步代碼塊objectB");  
  26.                 }  
  27.             }  
  28.   
  29.         } else {  
  30.             synchronized (objectB) {  
  31.                 try {  
  32.                     Thread.sleep(1000);  
  33.                 } catch (InterruptedException e) {  
  34.                     e.printStackTrace();  
  35.                 }  
  36.                 System.out.println(threadName   
  37.                         + "已進入同步代碼塊objectB,准備進入objectA");  
  38.                 synchronized (objectA) {  
  39.                     System.out.println(threadName   
  40.                             + "已經進入同步代碼塊objectA");  
  41.                 }  
  42.             }  
  43.         }  
  44.     }  
  45.   
  46.     public static void main(String[] args) {  
  47.         DeadLockThread deadlock1 = new DeadLockThread();  
  48.         DeadLockThread deadlock2 = new DeadLockThread();  
  49.         deadlock1.flag = true;  
  50.         deadlock2.flag = false;  
  51.         Thread thread1 = new Thread(deadlock1);  
  52.         Thread thread2 = new Thread(deadlock2);  
  53.         thread1.start();  
  54.         thread2.start();  
  55.   
  56.     }  
  57.   
  58. }  
[java] view plain copy
  1. 當前線程 為:Thread-0 flag = true  
  2. 當前線程 為:Thread-1 flag = false  
  3. Thread-1已進入同步代碼塊objectB,准備進入objectA  
  4. Thread-0已進入同步代碼塊objectA,准備進入objectB  



http://blog.csdn.net/joejames/article/details/37960873

http://www.cnblogs.com/XHJT/p/3898970.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM