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

Java多線程中的死鎖詳解

 更新時間:2023年08月26日 08:29:48   作者:一只愛打拳的程序猿  
這篇文章主要介紹了Java多線程中的死鎖詳解,死鎖是指兩個或多個線程在執(zhí)行過程中,因爭奪資源而造成的一種互相等待的現(xiàn)象,如果不提前預(yù)防或外界干擾,這些線程將無法執(zhí)行下去,需要的朋友可以參考下

前言

死鎖(Deadlock)是指兩個或多個線程在執(zhí)行過程中,因爭奪資源而造成的一種互相等待的現(xiàn)象

如果不提前預(yù)防或外界干擾,這些線程將無法執(zhí)行下去。

因此,本篇博文講解造成死鎖的原因以及解決方案。

1. 造成死鎖的原因

死鎖是多個線程在相互等待對方所占有的鎖才能繼續(xù)執(zhí)行下去,造成線程都被阻塞都無法執(zhí)行下去,也釋放不了線程自己的鎖資源,造成僵局。

舉例說明:

我和朋友去拉面館吃面,我先拿起了辣椒他拿起了醋。此時他想要辣椒、我想要醋,但我倆誰也不讓誰。

我對他說:你先把辣椒給我,我用完了就把醋給你。他對我說:你先把醋給我,我用完了就把辣椒給你。

我和他也不讓誰,最后導(dǎo)致死鎖。在上述例子中,辣椒和醋就是兩個鎖,我和他就是兩個線程。關(guān)于死鎖會引申的一個哲學(xué)家就餐問題。

2. 哲學(xué)家就餐問題

哲學(xué)家就餐問題是一個經(jīng)典的并發(fā)編程問題,它描述的是五個哲學(xué)家圍坐在一張圓形餐桌旁,每個哲學(xué)家面前有一碗飯和一只筷子,碗和筷子都是共享資源。

哲學(xué)家需要用一雙筷子來吃飯,但是只有相鄰的兩個哲學(xué)家之間有一只筷子,因此他們必須在餐桌上競爭筷子,才能拿到一雙筷子吃飯。

這個問題會引發(fā)死鎖(Deadlock)和饑餓(Starvation)等并發(fā)編程中的經(jīng)典問題。

如果所有哲學(xué)家同時都想獲取餐具,但每個哲學(xué)家只能等待旁邊的哲學(xué)家放下筷子才能獲取餐具,這可能會導(dǎo)致死鎖。

如果所有哲學(xué)家只有在其他人都吃到飯才能拿到自己的餐具,那么有些哲學(xué)家可能會因為等待時間太長而饑餓。

代碼案例:

有兩個哲學(xué)家在進行就餐,哲學(xué)家1獲取到筷子1后繼續(xù)嘗試獲取筷子2,哲學(xué)家2獲取到筷子2后繼續(xù)嘗試獲取筷子1,造成了死鎖狀態(tài)。

public class DeadlockDemo {
        public static void main(String[] args) {
            Object obj1 = new Object();//筷子1
            Object obj2 = new Object();//筷子2
            // 線程1獲取obj1,然后等待obj2
            Thread thread1 = new Thread(() -> {
                synchronized (obj1) {
                    System.out.println(Thread.currentThread().getName() + " 獲取 obj1鎖");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj2) {
                        System.out.println(Thread.currentThread().getName() + " 獲取 obj2鎖");
                    }
                }
            }, "哲學(xué)家 1");
            // 線程2獲取obj2,然后等待obj1
            Thread thread2 = new Thread(() -> {
                synchronized (obj2) {
                    System.out.println(Thread.currentThread().getName() + " 獲取 obj2鎖");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj1) {
                        System.out.println(Thread.currentThread().getName() + " 獲取 obj1鎖");
                    }
                }
            }, "哲學(xué)家 2");
            t1.start();
            t2.start();
        }
}

運行后打印:

上述代碼,中 thread1 是哲學(xué)家1,thread2 是哲學(xué)家2,obj1 鎖和 obj2 鎖分別代表兩只筷子。

哲學(xué)家1 占用了 obj1 鎖,哲學(xué)家2 占用了 obj2 鎖。

此時 哲學(xué)家1 在擁有 obj1 時獲取 obj2 是獲取不到的,哲學(xué)家2 在擁有 obj2 時獲取 obj1 也是獲取不到的。

這樣就會造成死鎖。也就是本篇文章開頭所說的,一個線程處于永久獲取到鎖的狀態(tài),其他線程無限阻塞等待,這就造成了死鎖。

2.1 造成死鎖的原因

  • 互斥:一個資源只能被一個進程獨占,即該資源只能被一個進程占有或使用。
  • 請求和保持:進程已經(jīng)保持了至少一個資源,并還在嘗試獲取其他進程保持的資源。
  • 不可搶占:某個資源只能由占有它的線程釋放,不能被其他線程強制占有或搶占。
  • 循環(huán)等待:假設(shè)一個隊列有{t1,t2,t3}這三個線程,t1 等待 t2 所占資源,t2 等待 t3 所占資源,t3 等待 t1 所占資源,這樣就會造成循環(huán)等待。 

2.2 解決死鎖問題

解決死鎖問題,最好的方式就是預(yù)防死鎖。我們把鎖按照順序進行編號,并且約定每個線程在獲取多把鎖的時候必須先獲取編號小的,后獲取編號大的。這樣就不會形成死鎖了。

因為,最先獲取編號小鎖的線程會優(yōu)先完成相應(yīng)任務(wù)。輪到其他線程再獲取小編號鎖時,鎖就處于空閑狀態(tài)了。

代碼案例:

public class DeadlockDemo {
        public static void main(String[] args) {
            Object obj1 = new Object();//筷子1
            Object obj2 = new Object();//筷子2
            Thread t1 = new Thread(() -> {
                synchronized (obj1) {
                    System.out.println(Thread.currentThread().getName() + " 獲取 obj1鎖");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj2) {
                        System.out.println(Thread.currentThread().getName() + " 獲取 obj2鎖");
                    }
                }
            }, "哲學(xué)家 1");
            Thread t2 = new Thread(() -> {
                synchronized (obj1) {
                    System.out.println(Thread.currentThread().getName() + " 獲取 obj2鎖");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj2) {
                        System.out.println(Thread.currentThread().getName() + " 獲取 obj1鎖");
                    }
                }
            }, "哲學(xué)家 2");
            t1.start();
            t2.start();
        }
}

運行后打?。?/p>

在上述代碼中,我們創(chuàng)建了兩個鎖對象 obj1 和 obj2 分別代表兩只筷子,并創(chuàng)建兩個線程 thread1 和 thread 2 分別代表兩個哲學(xué)家。

當(dāng) 哲學(xué)家1 首先獲取到 obj1 后,由于 obj2 并未線程占用,則立馬獲取 obj2 ,獲得了兩雙筷子,就餐后釋放 obj1 和 obj2。

這時 哲學(xué)家2 嘗試獲取 obj2 和 obj1 時,發(fā)現(xiàn)兩雙筷子都沒人使用,直接開始就餐。

總結(jié)

什么是死鎖?

當(dāng)多個線程并發(fā)后,線程在占有鎖資源的情況下還嘗試獲取別的線程所占有的鎖資源。

這樣就會操作線程永遠(yuǎn)獲取不到其他鎖資源,也不能釋放本身鎖資源。

從而形成的一種僵局,這就是死鎖。

造成死鎖的原因是什么?

造成死鎖的原因有,互斥、請求和保持、不可搶占、循環(huán)等待。(文章中有講解)

死鎖的解決方案

我們可以對多個鎖按照順序進行編號,并約定每個線程在使用多把鎖時優(yōu)先使用最小編號的鎖,這樣就能保證其他線程再獲取小編號鎖時,鎖資源已得到釋放。

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

相關(guān)文章

  • 解決報錯:java:讀取jar包時出錯:error in opening zip file問題

    解決報錯:java:讀取jar包時出錯:error in opening zip 

    文章總結(jié):解決Java讀取jar包時出錯的問題,通過下載源碼并刷新項目解決了問題,希望對大家有所幫助
    2024-11-11
  • idea文件夾平鋪問題及解決

    idea文件夾平鋪問題及解決

    用戶發(fā)現(xiàn)IntelliJ IDEA文件夾平鋪顯示異常,通過右側(cè)齒輪按鈕調(diào)整設(shè)置,將HideEmptyMiddlePackages改為CompactMiddlePackages后,問題解決,界面恢復(fù)正常
    2025-07-07
  • MyBatis 中的@Param注解最佳實踐

    MyBatis 中的@Param注解最佳實踐

    在 MyBatis 中,@Param 注解的作用是為方法參數(shù)指定一個在 XML 映射文件或注解 SQL 中引用的名稱,對于你的問題,是否可以不寫,取決于MyBatis的版本和參數(shù)類型,這篇文章給大家介紹MyBatis中的@Param注解,感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • Maven 主模塊和子模塊pom.xml依賴聲明

    Maven 主模塊和子模塊pom.xml依賴聲明

    這篇文章主要介紹了Maven 主模塊和子模塊pom.xml依賴聲明,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java關(guān)于MyBatis緩存詳解

    Java關(guān)于MyBatis緩存詳解

    緩存的重要性是不言而喻的,使用緩存,我們可以避免頻繁的與數(shù)據(jù)庫進行交互,尤其是在查詢越多、緩存命中率越高的情況下,使用緩存對性能的提高更明顯。本文將給大家詳細(xì)的介紹,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值
    2021-09-09
  • Spring整合redis(jedis)實現(xiàn)Session共享的過程

    Spring整合redis(jedis)實現(xiàn)Session共享的過程

    這篇文章主要介紹了Spring整合redis(jedis)實現(xiàn)Session共享,需要的朋友可以參考下
    2018-06-06
  • Java計算兩個時間段的差的實例詳解

    Java計算兩個時間段的差的實例詳解

    在本篇內(nèi)容中,我們給大家整理了關(guān)于Java計算兩個時間段的差的實例內(nèi)容,并做了詳細(xì)分析,有需要的朋友們學(xué)習(xí)下。
    2022-11-11
  • Mybatis 插入一條或批量插入 返回帶有自增長主鍵記錄的實例

    Mybatis 插入一條或批量插入 返回帶有自增長主鍵記錄的實例

    下面小編就為大家分享一篇Mybatis 插入一條或批量插入 返回帶有自增長主鍵記錄的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • Java利用Geotools實現(xiàn)不同坐標(biāo)系之間坐標(biāo)轉(zhuǎn)換

    Java利用Geotools實現(xiàn)不同坐標(biāo)系之間坐標(biāo)轉(zhuǎn)換

    GeoTools 是一個開源的 Java GIS 工具包,可利用它來開發(fā)符合標(biāo)準(zhǔn)的地理信息系統(tǒng)。本文將利用工具包Geotools實現(xiàn)不同坐標(biāo)系之間坐標(biāo)轉(zhuǎn)換,感興趣的可以了解一下
    2022-08-08
  • Java基礎(chǔ)之淺談hashCode()和equals()

    Java基礎(chǔ)之淺談hashCode()和equals()

    今天給大家?guī)淼氖顷P(guān)于Java基礎(chǔ)的相關(guān)知識,文章圍繞著hashCode()和equals()展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評論

九龙县| 昔阳县| 夏河县| 汕尾市| 苍梧县| 罗江县| 宜章县| 新沂市| 东丰县| 沈阳市| 会东县| 中山市| 色达县| 洛隆县| 横山县| 广昌县| 郓城县| 宜宾县| 宣恩县| 鄄城县| 疏附县| 通河县| 涞水县| 莱州市| 丹棱县| 贞丰县| 固阳县| 安岳县| 阿拉善盟| 平顺县| 武夷山市| 安多县| 浙江省| 蕉岭县| 太保市| 河间市| 云阳县| 彭水| 黔江区| 金溪县| 武乡县|