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

Java死鎖的產(chǎn)生原因及解決方法總結(jié)

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

一. 死鎖

1. 概念

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

2. 死鎖案例

雖然我們現(xiàn)在已經(jīng)知道了死鎖的概念,但具體什么時候會產(chǎn)生死鎖,相信很多小伙伴肯定還是弄不不清楚。所以接下來就給大家設(shè)計一個會產(chǎ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í)行過程中會互相等待對方的鎖,從而形成了死鎖。如果我們運行該程序,就會看到兩個線程互相等待對方釋放自己占用的鎖,這最終會導(dǎo)致所有的線程都被阻塞。上述案例中死鎖的產(chǎn)生原因,如下圖所示:

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

3. 產(chǎn)生條件

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

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

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

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

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

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

4. 解決辦法

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

避免使用多個鎖;

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

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

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

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

5. 案例優(yōu)化

接下來就把上面產(chǎn)生死鎖的案例優(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í)行。

二. 結(jié)語

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

以上就是Java死鎖的產(chǎn)生原因及解決方法總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Java死鎖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot實戰(zhàn)之實現(xiàn)結(jié)果的優(yōu)雅響應(yīng)案例詳解

    SpringBoot實戰(zhàn)之實現(xiàn)結(jié)果的優(yōu)雅響應(yīng)案例詳解

    這篇文章主要介紹了SpringBoot實戰(zhàn)之實現(xiàn)結(jié)果的優(yōu)雅響應(yīng)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • java文件對話框過濾特定文件類型示例

    java文件對話框過濾特定文件類型示例

    文件作為存儲數(shù)據(jù)的單元,會根據(jù)數(shù)據(jù)類型產(chǎn)生很多分類,也就是所謂的文件類型。在對數(shù)據(jù)文件進(jìn)行操作時,常常需要根據(jù)不同的文件類型來作不同的處理。本實例實現(xiàn)的是讀取文件夾指定類型的文件并顯示到表格控件中
    2014-02-02
  • Springboot的啟動原理詳細(xì)解讀

    Springboot的啟動原理詳細(xì)解讀

    這篇文章主要介紹了Springboot的啟動原理詳細(xì)解讀,springboot項目一般都是打包成jar包直接運行main方法啟動,當(dāng)然也可以跟傳統(tǒng)的項目一樣打包war包放在tomcat里面啟動.那么springboot怎么直接通過main方法啟動呢,需要的朋友可以參考下
    2023-11-11
  • java反射之方法反射的基本操作方法

    java反射之方法反射的基本操作方法

    下面小編就為大家?guī)硪黄猨ava反射之方法反射的基本操作方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • JAVA maven項目使用釘釘SDK獲取token、用戶

    JAVA maven項目使用釘釘SDK獲取token、用戶

    這篇文章主要介紹了JAVA maven項目使用釘釘SDK獲取token、用戶,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • SpringMVC 攔截器不攔截靜態(tài)資源的三種處理方式方法

    SpringMVC 攔截器不攔截靜態(tài)資源的三種處理方式方法

    本篇文章主要介紹了SpringMVC 攔截器不攔截靜態(tài)資源的三種處理方式方法,詳細(xì)的介紹了三種方法,有興趣的可以了解一下。
    2017-01-01
  • springboot項目部署在linux上運行的兩種方式小結(jié)

    springboot項目部署在linux上運行的兩種方式小結(jié)

    這篇文章主要介紹了springboot項目部署在linux上運行的兩種方式小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java編譯命令和啟動命令的使用方式

    java編譯命令和啟動命令的使用方式

    Java開發(fā)中,編譯源文件需使用javac命令,該命令能將.java文件編譯成.class字節(jié)碼文件,后者可在JVM上運行,常用編譯選項包括-d指定輸出目錄,-classpath設(shè)置類搜索路徑等,啟動Java程序使用java命令,它加載并運行包含main方法的類
    2024-10-10
  • Java實現(xiàn)插入公式到PPT的示例代碼

    Java實現(xiàn)插入公式到PPT的示例代碼

    PPT中可插入公式,用于放映時演示相關(guān)內(nèi)容的論證、推算的依據(jù)。通過代碼,我們可借助特定的工具來實現(xiàn)在PPT中的插入公式,本文將對此作詳細(xì)介紹
    2022-07-07
  • 基于GeoTools和SpringBoot的省域駕車最快路線規(guī)劃方法

    基于GeoTools和SpringBoot的省域駕車最快路線規(guī)劃方法

    本文探討基于GeoTools與SpringBoot的省域駕車最快路線規(guī)劃方法,解決復(fù)雜路況與地理因素影響,通過天地圖API計算并存儲距離數(shù)據(jù),展示湖南、新疆、黑龍江等地的路線成果,為交通與經(jīng)濟(jì)影響評估提供參考,感興趣的朋友快來一起學(xué)習(xí)吧
    2025-07-07

最新評論

运城市| 固阳县| 资阳市| 天全县| 衡山县| 宜宾县| 安庆市| 闵行区| 宁武县| 丁青县| 沅江市| 阳新县| 福海县| 余庆县| 新沂市| 北碚区| 康保县| 施甸县| 吴旗县| 桓台县| 百色市| 米脂县| 普兰店市| 泾川县| 日照市| 板桥市| 梨树县| 武城县| 兴城市| 临夏县| 玉屏| 巴林左旗| 易门县| 卓尼县| 会东县| 闽侯县| 泽州县| 始兴县| 阳春市| 顺昌县| 堆龙德庆县|