欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java死鎖的產生原因及解決方法總結

 更新時間:2023年11月06日 09:24:22   作者:一一哥Sun  
Java中的死鎖是指多個線程同時占用一些共享資源且彼此相互等待,從而導致所有的線程都被阻塞,不能繼續(xù)執(zhí)行程序的情況,本文小編給大家介紹了Java死鎖的產生原因及解決方法總結,需要的朋友可以參考下

一. 死鎖

1. 概念

Java中的死鎖是指多個線程同時占用一些共享資源且彼此相互等待,從而導致所有的線程都被阻塞,不能繼續(xù)執(zhí)行程序的情況。這就好比在一個十字路口,沒有交警也沒有紅綠燈指揮通行,所有的車輛都占據(jù)道路且互相等待對方讓出路權,此時就很容易造成道路堵死,這其實就是道路的“死鎖”。如下圖所示:

2. 死鎖案例

雖然我們現(xiàn)在已經知道了死鎖的概念,但具體什么時候會產生死鎖,相信很多小伙伴肯定還是弄不不清楚。所以接下來就給大家設計一個會產生死鎖的代碼案例,如下所示:

/**
 * @author 一一哥Sun
 * @company 千鋒教育
 */
public class Demo21 {
    // 定義2個鎖定的對象
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void method1() {
        // 鎖定對象1
        synchronized (lock1) {
            System.out.println("Method 1: 獲取對象lock1的鎖");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 鎖定對象2
            synchronized (lock2) {
                System.out.println("Method 1: 獲取對象lock2的鎖");
            }
        }
     }

    public void method2() {
        // 鎖定對象2
        synchronized (lock2) {
            System.out.println("Method 2: 獲取對象lock2的鎖");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 鎖定對象1
            synchronized (lock1) {
                System.out.println("Method 2: 獲取對象lock1的鎖");
            }
        }
    }

    public static void main(String[] args) {
        final Demo21 example = new Demo21();

        Thread thread1 = new Thread(new Runnable() {
            public void run() {
                example.method1();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            public void run() {
                example.method2();
            }
        });

        //開啟線程
        thread1.start();
        thread2.start();
    }
}

在上面的案例中,定義了兩個方法method1和method2,這兩個方法分別占用了lock1和lock2兩個鎖,并且在執(zhí)行過程中會互相等待對方的鎖,從而形成了死鎖。如果我們運行該程序,就會看到兩個線程互相等待對方釋放自己占用的鎖,這最終會導致所有的線程都被阻塞。上述案例中死鎖的產生原因,如下圖所示:

根據(jù)上面的案例,你可以總結出會導致死鎖的條件嗎?我們繼續(xù)往下看。

3. 產生條件

其實一個Java程序要想產生死鎖,也并不是那么容易,只有同時滿足以下條件才行:

互斥條件:多個線程需同時訪問一個共享資源,但每次只能有一個線程訪問該資源;

請求和保持條件:一個線程在持有一個資源的同時,還想請求另一個資源;

不可剝奪條件:已經分配的資源不能被其他線程剝奪;

循環(huán)(環(huán)路)等待條件:多個線程形成了一個循環(huán)等待資源的鏈路,例如線程A等待線程B釋放自己所占用的資源,線程B等待線程C釋放自己所占用的資源,而線程C又等待線程A釋放自己所占用的資源。

只有同時滿足了以上條件,程序中才會產生死鎖。既然我們現(xiàn)在知道了死鎖的產生條件,那又該怎么解決呢?

4. 解決辦法

我們知道,當出現(xiàn)死鎖時,所有的線程都會被阻塞,且不能再繼續(xù)執(zhí)行程序,所以我們必須解決死鎖。一般情況下,我們可以通過以下方式來避免線程死鎖:

避免使用多個鎖;

盡可能減少同步代碼塊的長度;

嘗試改變鎖的獲取順序,避免線程之間形成循環(huán)等待;

使用定時鎖,當?shù)却龝r間超過一定的時間值后就自動釋放鎖

以上就是打破死鎖條件的解決辦法,但是具體放到Java代碼中又是怎么樣的呢?接下來就把上面產生死鎖的代碼修改一下,解決死鎖問題。

5. 案例優(yōu)化

接下來就把上面產生死鎖的案例優(yōu)化一下,解決掉案例中的死鎖,代碼如下:

public class Demo22 {
    // 定義2個鎖定的對象
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void method1() {
        //鎖定對象
        synchronized(lock1) {
            System.out.println("Method 1: 獲取對象鎖lock 1");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            synchronized(lock2) {
                System.out.println("Method 1: 獲取對象鎖lock 2");
            }
        }
    }

    public void method2() {
        synchronized(lock1) {
            System.out.println("Method 2: 獲取對象鎖lock 1");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            synchronized(lock2) {
                System.out.println("Method 2: 獲取對象鎖lock 2");
            }
        }
    }

    public static void main(String[] args) {
        final Demo22 demo = new Demo22();

        //定義兩個線程
        Thread thread1 = new Thread(new Runnable() {
        	@Override
            public void run() {
            	demo.method1();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
        	@Override
            public void run() {
            	demo.method2();
            }
        });

        //開啟線程
        thread1.start();
        thread2.start();
    }
}

上面的這個案例與之前的案例代碼幾乎一樣,但與之不同的是,本案例中的方法method1和method2,都是先占用lock1鎖,再占用lock2鎖,這樣就避免了死鎖的發(fā)生,因為這兩個方法占用鎖的順序是一致的。所以我們在編寫多線程代碼時,需要特別注意線程死鎖的問題,避免影響程序的正常執(zhí)行。

二. 結語

至此,小編就把Java中的死鎖給大家講解完畢了,現(xiàn)在你明白了嗎?我們在面試時經常會有面試官考察死鎖相關的內容,比如死鎖是怎么產生的?如何避免死鎖?所以今天的內容很重要,請各位一定要牢牢掌握哦。

以上就是Java死鎖的產生原因及解決方法總結的詳細內容,更多關于Java死鎖的資料請關注腳本之家其它相關文章!

相關文章

  • Java實現(xiàn)加鹽算法的兩種方法

    Java實現(xiàn)加鹽算法的兩種方法

    數(shù)據(jù)安全是一個重要的問題,本文主要介紹了Java實現(xiàn)加鹽算法的兩種方法,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • 一文徹底弄懂Java中MultipartFile接口和File類

    一文徹底弄懂Java中MultipartFile接口和File類

    MultipartFile是一個接口,我們可以理解為是Spring?給我們綁定的一個在使用文件上傳等時簡便實現(xiàn)的口子,這篇文章主要給大家介紹了關于如何通過一文徹底弄懂Java中MultipartFile接口和File類的相關資料,需要的朋友可以參考下
    2023-11-11
  • 淺析java并發(fā)中的Synchronized關鍵詞

    淺析java并發(fā)中的Synchronized關鍵詞

    這篇文章主要介紹了java并發(fā)中的Synchronized關鍵詞,本文通過思路代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • SpringBoot如何在普通類加載Spring容器

    SpringBoot如何在普通類加載Spring容器

    這篇文章主要介紹了SpringBoot如何在普通類加載Spring容器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • Kotlin-Coroutines中的async與await異步協(xié)程管理

    Kotlin-Coroutines中的async與await異步協(xié)程管理

    這篇文章主要為大家介紹了Kotlin-Coroutines中的async與await異步協(xié)程管理,提升程序性能解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • Spring Cloud使用Feign進行遠程調用的操作指南

    Spring Cloud使用Feign進行遠程調用的操作指南

    本文介紹了Feign作為聲明式HTTP客戶端在SpringCloud中的使用,從簡介、對比RestTemplate的問題、使用步驟,到日志配置、性能優(yōu)化和實際應用進行了詳細講解,包括如何通過Feign簡化接口調用,以及解決啟動時找不到FeignClient的問題,需要的朋友可以參考下
    2025-02-02
  • Spring容器初始化擴展點之ApplicationContextInitializer詳解

    Spring容器初始化擴展點之ApplicationContextInitializer詳解

    ApplicationContextInitializer是Spring框架提供的一個接口,用于在Spring應用上下文刷新之前對其進行自定義初始化,本文介紹Spring容器初始化擴展點之ApplicationContextInitializer,感興趣的朋友一起看看吧
    2025-02-02
  • SpringBoot啟動過程與自動配置過程解讀

    SpringBoot啟動過程與自動配置過程解讀

    本文詳解SpringBoot啟動流程及自動配置機制,涵蓋main方法初始化、環(huán)境配置、容器啟動等關鍵步驟,解析條件注解與spring.factories的智能配置邏輯,并提供自定義配置方法,強調其"約定優(yōu)于配置"的核心理念與工程化封裝特性
    2025-08-08
  • maven打包成第三方jar包且把pom依賴包打入進來的方法

    maven打包成第三方jar包且把pom依賴包打入進來的方法

    這篇文章主要介紹了maven打包成第三方jar包且把pom依賴包打入進來的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • java 面試題閏年判斷詳解及實例

    java 面試題閏年判斷詳解及實例

    這篇文章主要介紹了java面試題 閏年判斷的相關資料,需要的朋友可以參考下
    2017-03-03

最新評論