搜尋
首頁Javajava教程java開發中遇見死鎖的解決方法

這篇文章主要介紹了java 多執行緒死鎖詳解及簡單實例的相關資料,需要的朋友可以參考下

死鎖是這樣一種情形:多個執行緒同時被阻塞,它們中的一個或全部都在等待某個資源被釋放。由於執行緒被無限期地阻塞,因此程式不可能正常終止。

java 死鎖產生的四個必要條件:

#1>互斥使用,即當資源被一個執行緒使用(佔有)時,別的執行緒不能使用

2>不可搶佔,資源請求者不能強制從資源佔有者手中奪取資源,資源只能由資源佔有者主動釋放。

3>請求和維持,即當資源請求者在請求其他的資源的同時保持對原有資源的戰友。

4>循環等待,即存在一個等待佇列:P1佔有P2的資源,P2佔有P3的資源,P3佔有P1的資源。這樣就形成了一個等待環路。

當上述四個條件都成立的時候,便形成死鎖。當然,死鎖的情況下如果打破上述任何一個條件,便可讓死鎖消失。下面用java程式碼來模擬一下死鎖的產生。

解決死鎖問題的方法是:一種是用synchronized,一種是用Lock明確鎖定實作。

而如果不恰當的使用了鎖,且出現同時要鎖多個物件時,會出現死鎖情況,如下:

/*
 author by w3cschool.cc
 LockTest.java
 */
import java.util.Date;
public class LockTest {
  public static String obj1 = "obj1";
  public static String obj2 = "obj2";
  public static void main(String[] args) {
   LockA la = new LockA();
   new Thread(la).start();
   LockB lb = new LockB();
   new Thread(lb).start();
  }
}
class LockA implements Runnable{
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockA 开始执行");
     while(true){
      synchronized (LockTest.obj1) {
        System.out.println(new Date().toString() + " LockA 锁住 obj1");
        Thread.sleep(3000); // 此处等待是给B能锁住机会
        synchronized (LockTest.obj2) {
         System.out.println(new Date().toString() + " LockA 锁住 obj2");
         Thread.sleep(60 * 1000); // 为测试,占用了就不放
        }
      }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}
class LockB implements Runnable{
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockB 开始执行");
     while(true){
      synchronized (LockTest.obj2) {
        System.out.println(new Date().toString() + " LockB 锁住 obj2");
        Thread.sleep(3000); // 此处等待是给A能锁住机会
        synchronized (LockTest.obj1) {
         System.out.println(new Date().toString() + " LockB 锁住 obj1");
         Thread.sleep(60 * 1000); // 为测试,占用了就不放
        }
      }
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}

以上程式碼運行輸出結果為:

Tue May 05 10:51:06 CST 2015 LockB 开始执行
Tue May 05 10:51:06 CST 2015 LockA 开始执行
Tue May 05 10:51:06 CST 2015 LockB 锁住 obj2
Tue May 05 10:51:06 CST 2015 LockA 锁住 obj1

此時死鎖產生。

為了解決這個問題,我們不使用顯示的去鎖,我們用信號量去控制。

信號量可以控制資源能被多少執行緒訪問,這裡我們指定只能被一個執行緒訪問,就做到了類似鎖住。而信號量可以指定去獲取的超時時間,我們可以根據這個超時時間,去做一個額外處理。

對於無法成功取得的情況,一般就是重複嘗試,或指定嘗試的次數,也可以馬上退出

來看下如下程式碼:

/*
 author by w3cschool.cc
 UnLockTest.java
 */
import java.util.Date;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class UnLockTest {
  public static String obj1 = "obj1";
  public static final Semaphore a1 = new Semaphore(1);
  public static String obj2 = "obj2";
  public static final Semaphore a2 = new Semaphore(1);
  public static void main(String[] args) {
   LockAa la = new LockAa();
   new Thread(la).start();
   LockBb lb = new LockBb();
   new Thread(lb).start();
  }
}
class LockAa implements Runnable {
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockA 开始执行");
     while (true) {
      if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
        System.out.println(new Date().toString() + " LockA 锁住 obj1");
        if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
         System.out.println(new Date().toString() + " LockA 锁住 obj2");
         Thread.sleep(60 * 1000); // do something
        }else{
         System.out.println(new Date().toString() + "LockA 锁 obj2 失败");
        }
      }else{
        System.out.println(new Date().toString() + "LockA 锁 obj1 失败");
      }
      UnLockTest.a1.release(); // 释放
      UnLockTest.a2.release();
      Thread.sleep(1000); // 马上进行尝试,现实情况下do something是不确定的
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}
class LockBb implements Runnable {
  public void run() {
   try {
     System.out.println(new Date().toString() + " LockB 开始执行");
     while (true) {
      if (UnLockTest.a2.tryAcquire(1, TimeUnit.SECONDS)) {
        System.out.println(new Date().toString() + " LockB 锁住 obj2");
        if (UnLockTest.a1.tryAcquire(1, TimeUnit.SECONDS)) {
         System.out.println(new Date().toString() + " LockB 锁住 obj1");
         Thread.sleep(60 * 1000); // do something
        }else{
         System.out.println(new Date().toString() + "LockB 锁 obj1 失败");
        }
      }else{
        System.out.println(new Date().toString() + "LockB 锁 obj2 失败");
      }
      UnLockTest.a1.release(); // 释放
      UnLockTest.a2.release();
      Thread.sleep(10 * 1000); // 这里只是为了演示,所以tryAcquire只用1秒,而且B要给A让出能执行的时间,否则两个永远是死锁
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
  }
}

#以上實例程式碼輸出結構為:

Tue May 05 10:59:13 CST 2015 LockA 开始执行
Tue May 05 10:59:13 CST 2015 LockB 开始执行
Tue May 05 10:59:13 CST 2015 LockB 锁住 obj2
Tue May 05 10:59:13 CST 2015 LockA 锁住 obj1
Tue May 05 10:59:14 CST 2015LockB 锁 obj1 失败
Tue May 05 10:59:14 CST 2015LockA 锁 obj2 失败
Tue May 05 10:59:15 CST 2015 LockA 锁住 obj1
Tue May 05 10:59:15 CST 2015 LockA 锁住 obj2

【相關推薦】

1. Java影片教學

2. JAVA教學手冊

3. 極客學院Java視訊教學

以上是java開發中遇見死鎖的解決方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?如何將Maven或Gradle用於高級Java項目管理,構建自動化和依賴性解決方案?Mar 17, 2025 pm 05:46 PM

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?如何使用適當的版本控制和依賴項管理創建和使用自定義Java庫(JAR文件)?Mar 17, 2025 pm 05:45 PM

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?如何使用咖啡因或Guava Cache等庫在Java應用程序中實現多層緩存?Mar 17, 2025 pm 05:44 PM

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?如何將JPA(Java持久性API)用於具有高級功能(例如緩存和懶惰加載)的對象相關映射?Mar 17, 2025 pm 05:43 PM

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Java的類負載機制如何起作用,包括不同的類載荷及其委託模型?Mar 17, 2025 pm 05:35 PM

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器