最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java死鎖避免的五種方法舉例總結

 更新時間:2025年05月07日 08:33:14   作者:EthanMilk  
這篇文章主要介紹了Java死鎖避免的五種方法,包括按固定順序加鎖、使用tryLock+超時、一次性申請所有資源、使用Lock替代synchronized以及檢測與恢復,需要的朋友可以參考下

前言

死鎖(Deadlock)是指多個線程互相持有對方需要的資源,導致所有線程都無法繼續(xù)執(zhí)行的情況。Java 中可以通過以下方法避免死鎖:

造成死鎖的?個原因:

  • ?個資源每次只能被?個線程使?

  • ?個線程在阻塞等待某個資源時,不釋放已占有資源

  • ?個線程已經(jīng)獲得的資源,在未使?完之前,不能被強?剝奪

  • 若?線程形成頭尾相接的循環(huán)等待資源關系

這是造成死鎖必須要達到的4個條件,如果要避免死鎖,只需要不滿?其中某?個條件即可。?其中前3 個條件是作為鎖要符合的條件,所以要避免死鎖就需要打破第4個條件,不出現(xiàn)循環(huán)等待鎖的關系。

在開發(fā)過程中:

  • 要注意加鎖順序,保證每個線程按同樣的順序進?加鎖

  • 要注意加鎖時限,可以針對所設置?個超時時間

  • 要注意死鎖檢查,這是?種預防機制,確保在第?時間發(fā)現(xiàn)死鎖并進?解決

1. 死鎖產(chǎn)生的四個必要條件

要避免死鎖,首先要理解死鎖發(fā)生的條件(必須全部滿足):

  • 互斥條件:資源一次只能被一個線程占用。

  • 占有并等待:線程持有資源的同時,等待其他資源。

  • 不可搶占:線程持有的資源不能被其他線程強行奪走。

  • 循環(huán)等待:多個線程形成環(huán)形等待鏈(A 等 B,B 等 C,C 等 A)。

只要破壞其中任意一個條件,就能避免死鎖!

2. 避免死鎖的 5 種方法

方法 1:按固定順序獲取鎖(破壞循環(huán)等待)

核心思想:所有線程按相同的順序申請鎖,避免循環(huán)依賴。

正確示例

public void transfer(Account from, Account to, int amount) {
    // 規(guī)定:先鎖 id 小的賬戶,再鎖 id 大的賬戶
    Account first = from.getId() < to.getId() ? from : to;
    Account second = from.getId() < to.getId() ? to : from;

    synchronized (first) {
        synchronized (second) {
            if (from.getBalance() >= amount) {
                from.debit(amount);
                to.credit(amount);
            }
        }
    }
}

為什么能避免死鎖?所有線程都按 id 順序加鎖,不會出現(xiàn) A 鎖 1 → 等 2 和 B 鎖 2 → 等 1 的情況。

方法 2:使用 tryLock + 超時(破壞占有并等待)

核心思想:如果拿不到鎖,就釋放已持有的鎖,避免無限等待。

正確示例(ReentrantLock)

public boolean transfer(Account from, Account to, int amount, long timeout) throws InterruptedException {
    long startTime = System.currentTimeMillis();
    while (true) {
        if (from.lock.tryLock()) { // 嘗試獲取第一把鎖
            try {
                if (to.lock.tryLock()) { // 嘗試獲取第二把鎖
                    try {
                        if (from.getBalance() >= amount) {
                            from.debit(amount);
                            to.credit(amount);
                            return true;
                        }
                    } finally {
                        to.lock.unlock();
                    }
                }
            } finally {
                from.lock.unlock(); // 釋放第一把鎖
            }
        }
        // 超時檢查
        if (System.currentTimeMillis() - startTime >= timeout) {
            return false;
        }
        Thread.sleep(100); // 避免 CPU 忙等待
    }
}

優(yōu)點

  • 不會無限等待,超時后可以重試或回滾。

  • 適用于高并發(fā)場景(如支付系統(tǒng))。

方法 3:一次性申請所有資源(破壞占有并等待)

核心思想:使用一個全局鎖,一次性申請所有需要的資源。

正確示例

public class AccountManager {
    private static final Object globalLock = new Object();

    public void transfer(Account from, Account to, int amount) {
        synchronized (globalLock) { // 全局鎖保護所有賬戶
            if (from.getBalance() >= amount) {
                from.debit(amount);
                to.credit(amount);
            }
        }
    }
}

缺點:并發(fā)度降低(所有轉(zhuǎn)賬操作串行化)。

方法 4:使用 Lock 替代 synchronized(更靈活的控制)

ReentrantLock 比 synchronized 更靈活,可以避免死鎖:

Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();

public void methodA() {
    boolean gotLock1 = false;
    boolean gotLock2 = false;
    try {
        gotLock1 = lock1.tryLock(1, TimeUnit.SECONDS);
        gotLock2 = lock2.tryLock(1, TimeUnit.SECONDS);
        if (gotLock1 && gotLock2) {
            // 執(zhí)行業(yè)務邏輯
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } finally {
        if (gotLock1) lock1.unlock();
        if (gotLock2) lock2.unlock();
    }
}

方法 5:檢測與恢復(允許死鎖發(fā)生,但能自動恢復)

適用于復雜系統(tǒng)(如數(shù)據(jù)庫、分布式系統(tǒng)):

1.檢測死鎖

使用 ThreadMXBean 查找死鎖:

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads();
if (threadIds != null) {
    System.out.println("檢測到死鎖!");
}

2.恢復策略

強制終止某個線程(如 thread.interrupt())。

回滾事務(數(shù)據(jù)庫場景)。

3. 死鎖案例分析

? 錯誤代碼(會導致死鎖)

public void transfer(Account from, Account to, int amount) {
    synchronized (from) {  // 線程1:鎖 from → 等 to
        synchronized (to) { // 線程2:鎖 to → 等 from
            if (from.getBalance() >= amount) {
                from.debit(amount);
                to.credit(amount);
            }
        }
    }
}

死鎖場景

  • 線程1:transfer(accountA, accountB, 100)

  • 線程2:transfer(accountB, accountA, 200)

  • 結果:互相等待,死鎖!

4. 總結

方法適用場景優(yōu)點缺點
固定順序加鎖簡單鎖依賴實現(xiàn)簡單需要全局排序規(guī)則
tryLock + 超時高并發(fā)系統(tǒng)避免無限等待代碼復雜度高
全局鎖低并發(fā)場景絕對安全性能差(串行化)
Lock 替代 synchronized需要更細粒度控制靈活(可中斷、超時)需手動釋放鎖
檢測與恢復數(shù)據(jù)庫、分布式系統(tǒng)適用于復雜場景實現(xiàn)復雜

最佳實踐

  • 盡量用 tryLock + 超時(推薦 ReentrantLock)。

  • 如果必須用 synchronized,按固定順序加鎖。

  • 避免嵌套鎖(如 synchronized 里再調(diào) synchronized 方法)。

  • 使用工具檢測死鎖(如 jstack、ThreadMXBean)。

到此這篇關于Java死鎖避免的五種方法的文章就介紹到這了,更多相關Java死鎖避免內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Springboot整合freemarker 404問題解決方案

    Springboot整合freemarker 404問題解決方案

    這篇文章主要介紹了Springboot整合freemarker 404問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • Springboot整合Activiti操作詳解

    Springboot整合Activiti操作詳解

    這篇文章主要給大家詳細介紹了Springboot整合Activiti的操作流程,文中流程步驟和代碼示例介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下
    2023-07-07
  • SpringSecurity權限控制實現(xiàn)原理解析

    SpringSecurity權限控制實現(xiàn)原理解析

    這篇文章主要介紹了SpringSecurity權限控制實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • SpringCloud-Hystrix實現(xiàn)原理總結

    SpringCloud-Hystrix實現(xiàn)原理總結

    通過hystrix可以解決雪崩效應問題,它提供了資源隔離、降級機制、融斷、緩存等功能。接下來通過本文給大家分享SpringCloud-Hystrix實現(xiàn)原理,感興趣的朋友一起看看吧
    2021-05-05
  • java類和對象原理與用法分析

    java類和對象原理與用法分析

    這篇文章主要介紹了java類和對象原理與用法,結合實例形式分析了java類和對象的相關概念、功能、原理、使用技巧與操作注意事項,需要的朋友可以參考下
    2020-02-02
  • Java中的字符型文件流FileReader和FileWriter詳細解讀

    Java中的字符型文件流FileReader和FileWriter詳細解讀

    這篇文章主要介紹了Java中的字符型文件流FileReader和FileWriter詳細解讀,與字節(jié)型文件流不同,字節(jié)型文件流讀取和寫入的都是一個又一個的字節(jié),而字符型文件流操作的單位是一個又一個的字符,字符型流認為一個字母是一個字符,而一個漢字也是一個字符,需要的朋友可以參考下
    2023-10-10
  • Java操作MongoDB事務未生效的常見場景及解決方案

    Java操作MongoDB事務未生效的常見場景及解決方案

    在 Java 開發(fā)中,使用 MongoDB 存儲數(shù)據(jù)時,事務的正確使用至關重要,然而,在實際開發(fā)過程中,經(jīng)常會遇到 MongoDB 事務沒有生效的情況,本文我將結合多年實踐經(jīng)驗,深入剖析事務未生效的常見場景,并給出詳細的解決方案,需要的朋友可以參考下
    2025-07-07
  • SpringBoot快速實現(xiàn)IP地址解析的全攻略

    SpringBoot快速實現(xiàn)IP地址解析的全攻略

    在當今的互聯(lián)網(wǎng)應用中,IP地址解析已成為許多系統(tǒng)不可或缺的功能,這篇文章主要為大家詳細介紹了如何使用SpringBoot快速實現(xiàn)IP地址解析,有需要的小伙伴可以了解下
    2026-02-02
  • IntelliJ IDEA將導入的項目轉(zhuǎn)成maven項目

    IntelliJ IDEA將導入的項目轉(zhuǎn)成maven項目

    這篇文章主要介紹了IntelliJ IDEA將導入的項目轉(zhuǎn)成maven項目,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • MyBatis學習筆記(二)之關聯(lián)關系

    MyBatis學習筆記(二)之關聯(lián)關系

    這篇文章主要介紹了MyBatis學習筆記(二)之關聯(lián)關系 的相關資料,需要的朋友可以參考下
    2016-02-02

最新評論

石台县| 湄潭县| 通城县| 南安市| 池州市| 抚松县| 泗水县| 偏关县| 巴林右旗| 南川市| 松滋市| 汝城县| 息烽县| 清镇市| 漳州市| 波密县| 富宁县| 双峰县| 伊春市| 双桥区| 宁晋县| 丹江口市| 徐水县| 余干县| 疏附县| 霍山县| 田东县| 沙田区| 临江市| 岢岚县| 济阳县| 瑞金市| 中江县| 蕉岭县| 广元市| 织金县| 东兰县| 吴川市| 淄博市| 梓潼县| 内乡县|