如何避免死鎖

死瑣

A線程持有a鎖,等待獲取b鎖;同時(shí)B線程持有b鎖,等待獲取a鎖。

死瑣條件

-- 獨(dú)占鎖:

  • 互斥:資源不能被共享,只能由一個(gè)進(jìn)程使用。
  • 請(qǐng)求與保持:進(jìn)程已獲得了一些資源,但因請(qǐng)求其它資源被阻塞時(shí),對(duì)已獲得的資源保持不放。
  • 不可搶占:有些系統(tǒng)資源是不可搶占的,當(dāng)某個(gè)進(jìn)程已獲得這種資源后,系統(tǒng)不能強(qiáng)行收回,只能由進(jìn)程使用完時(shí)自己釋放。

-- 循環(huán)等待:若干個(gè)進(jìn)程形成環(huán)形鏈,每個(gè)都占用對(duì)方申請(qǐng)的下一個(gè)資源。

    public static void main(String[] args) {
        final Object a = new Object();
        final Object b = new Object();
        Thread threadA = new Thread(() -> {
            synchronized (a) { //sleep 下可以確保死鎖
                System.out.println("now i in threadA-locka");
                synchronized (b) {
                    System.out.println("now i in threadA-lockb");
                }
            }
        });
        Thread threadB = new Thread(() -> {
            synchronized (b) { //sleep 下可以確保死鎖
                System.out.println("now i in threadB-lockb");
                synchronized (a) {
                    System.out.println("now i in threadB-locka");
                }
            }
        });
        threadA.start();
        threadB.start();
    }

如何避免

  • 避免多個(gè)線程互相持有對(duì)方線程所需要的獨(dú)占鎖的的情況
  1. 設(shè)置優(yōu)先級(jí)
  2. 超時(shí)放棄

ReentrantLock接口中: boolean tryLock(long time, TimeUnit unit)
設(shè)置超時(shí)時(shí)間,超時(shí)可以退出防止死鎖。

  1. 特定順序 A->B->C
  2. 盡量降低鎖的使用粒度,盡量不要幾個(gè)功能用同一把鎖,能鎖塊不鎖方法
  3. 不要用鎖
  • 用Concurrent類。比較常用的是ConcurrentHashMap、ConcurrentLinkedQueue、
    原子操作。AtomicBoolean等,實(shí)際應(yīng)用中java.util.concurrent.atomic十分有用,簡(jiǎn)單方便且效率比使用Lock更高
銀行家算法
  • 條件:
  1. 固定數(shù)量的進(jìn)程,固定數(shù)量的資源
  2. 進(jìn)程預(yù)先指定工作所需最大資源
  3. 進(jìn)程不能申請(qǐng)比總資源還多的資源
  4. 進(jìn)程等待時(shí)間有限
  5. 進(jìn)程在有限時(shí)間使用資源,用完歸還
  • 符號(hào):
    Available 系統(tǒng)可用資源數(shù)
    Max[i] 進(jìn)程i對(duì)資源的最大需求
    Allocation[i] 進(jìn)程i得到的資源數(shù)
    Need[i] 進(jìn)程i還需要的資源數(shù)
    Request[i] 進(jìn)程i當(dāng)前申請(qǐng)的資源數(shù)

  • 步驟:

  1. Request[i] <= need[i]
  2. Request[i] <= Available
  3. 分配資源,調(diào)整狀態(tài)
    Available = Available - Request[i]
    Allocation[i] = Allocation[i] + Request[i]
    Need[i] = Need[i] - Request[i]
  4. 判斷新?tīng)顟B(tài)是否有效,無(wú)效則退回,進(jìn)程等待
    初始化:Work = Available, finished = false
    檢測(cè):Need[i] <= Work

檢測(cè)死鎖

  1. jstack
    Jstack工具可以用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照。線程快照是當(dāng)前java虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現(xiàn)長(zhǎng)時(shí)間停頓的原因,如線程間死鎖、死循環(huán)、請(qǐng)求外部資源導(dǎo)致的長(zhǎng)時(shí)間等待等。

jps 查端口號(hào)
jstack pid

  1. jconsole
    圖形化工具
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 死鎖:有兩個(gè)或兩個(gè)以上線程相互持有對(duì)方所需要的資源,而使得這些線程無(wú)法往下執(zhí)行下去。在Java中程序執(zhí)行進(jìn)入對(duì)象的...
    Undo_0cc6閱讀 709評(píng)論 0 2
  • 死鎖是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去...
    MrWater_7b29閱讀 1,580評(píng)論 0 1
  • 所謂死鎖:是指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過(guò)程中,因爭(zhēng)奪資源而造成的一種互相等待的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推...
    一杯犀牛閱讀 1,222評(píng)論 0 2
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書(shū)筆記,整理的知識(shí)點(diǎn),也是為了防止忘記,尊重勞動(dòng)成果,轉(zhuǎn)載注明出處哦!如果你也喜歡,那...
    波波波先森閱讀 11,621評(píng)論 4 56
  • 雨滴 是洗去困惑著 環(huán)境美感魔法的解方 淚水 是解除約束靈魂魔咒 的靈藥 擁抱自然的恩賜 洗淨(jìng)所有 掩蓋初心善良的...
    蔡振源閱讀 186評(píng)論 0 4

友情鏈接更多精彩內(nèi)容