死鎖

死鎖的4個必要條件

產(chǎn)生死鎖必須同時滿足以下四個條件音婶,只要其中任一條件不成立,死鎖就不會發(fā)生。

  • 互斥條件:進程要求對所分配的資源(如打印機)進行排他性控制得滤,即在一段時間內(nèi)某 資源僅為一個進程所占有。此時若有其他進程請求該資源盒犹,則請求進程只能等待懂更。
  • 不剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走急膀,即只能 由獲得該資源的進程自己來釋放(只能是主動釋放)沮协。
  • 請求和保持條件:進程已經(jīng)保持了至少一個資源,但又提出了新的資源請求卓嫂,而該資源 已被其他進程占有慷暂,此時請求進程被阻塞,但對自己已獲得的資源保持不放命黔。
  • 循環(huán)等待條件:存在一種進程資源的循環(huán)等待鏈呜呐,鏈中每一個進程已獲得的資源同時被 鏈中下一個進程所請求就斤。即存在一個處于等待狀態(tài)的進程集合{Pl, P2, ..., pn},其中Pi等 待的資源被P(i+1)占有(i=0, 1, ..., n-1)蘑辑,Pn等待的資源被P0占有洋机,如圖2-15所示。
/**  
* 一個簡單的死鎖類  
* 當DeadLock類的對象flag==1時(td1)洋魂,先鎖定o1,睡眠500毫秒  
* 而td1在睡眠的時候另一個flag==0的對象(td2)線程啟動绷旗,先鎖定o2,睡眠500毫秒  
* td1睡眠結(jié)束后需要鎖定o2才能繼續(xù)執(zhí)行,而此時o2已被td2鎖定副砍;  
* td2睡眠結(jié)束后需要鎖定o1才能繼續(xù)執(zhí)行衔肢,而此時o1已被td1鎖定;  
* td1豁翎、td2相互等待角骤,都需要得到對方鎖定的資源才能繼續(xù)執(zhí)行,從而死鎖心剥。  
*/    
public class DeadLock implements Runnable {    
    public int flag = 1;    
    //靜態(tài)對象是類的所有對象共享的    
    private static Object o1 = new Object(), o2 = new Object();    
    @Override    
    public void run() {    
        System.out.println("flag=" + flag);    
        if (flag == 1) {    
            synchronized (o1) {    
                try {    
                    Thread.sleep(500);    
                } catch (Exception e) {    
                    e.printStackTrace();    
                }    
                synchronized (o2) {    
                    System.out.println("1");    
                }    
            }    
        }    
        if (flag == 0) {    
            synchronized (o2) {    
                try {    
                    Thread.sleep(500);    
                } catch (Exception e) {    
                    e.printStackTrace();    
                }    
                synchronized (o1) {    
                    System.out.println("0");    
                }    
            }    
        }    
    }    
    
    public static void main(String[] args) {    
            
        DeadLock td1 = new DeadLock();    
        DeadLock td2 = new DeadLock();    
        td1.flag = 1;    
        td2.flag = 0;    
        //td1,td2都處于可執(zhí)行狀態(tài)邦尊,但JVM線程調(diào)度先執(zhí)行哪個線程是不確定的。    
        //td2的run()可能在td1的run()之前運行    
        new Thread(td1).start();    
        new Thread(td2).start();    
    
    }    
}    

如何避免死鎖

在有些情況下死鎖是可以避免的优烧。三種用于避免死鎖的技術(shù):

  • 加鎖順序(線程按照一定的順序加鎖)
  • 加鎖時限(線程嘗試獲取鎖的時候加上一定的時限蝉揍,超過時-限則放棄對該鎖的請求,并釋放自己占有的鎖)
  • 死鎖檢測
    死鎖檢測是一個更好的死鎖預(yù)防機制畦娄,它主要是針對那些不可能實現(xiàn)按序加鎖并且鎖超時也不可行的場景又沾。
    每當一個線程獲得了鎖,會在線程和鎖相關(guān)的數(shù)據(jù)結(jié)構(gòu)中(map熙卡、graph等等)將其記下杖刷。除此之外,每當有線程請求鎖驳癌,也需要記錄在這個數(shù)據(jù)結(jié)構(gòu)中挺勿。
    當一個線程請求鎖失敗時,這個線程可以遍歷鎖的關(guān)系圖看看是否有死鎖發(fā)生喂柒。例如不瓶,線程A請求鎖7,但是鎖7這個時候被線程B持有灾杰,這時線程A就可以檢查一下線程B是否已經(jīng)請求了線程A當前所持有的鎖蚊丐。如果線程B確實有這樣的請求,那么就是發(fā)生了死鎖(線程A擁有鎖1艳吠,請求鎖7麦备;線程B擁有鎖7,請求鎖1)。
    當然凛篙,死鎖一般要比兩個線程互相持有對方的鎖這種情況要復(fù)雜的多黍匾。線程A等待線程B,線程B等待線程C呛梆,線程C等待線程D锐涯,線程D又在等待線程A。線程A為了檢測死鎖填物,它需要遞進地檢測所有被B請求的鎖纹腌。從線程B所請求的鎖開始,線程A找到了線程C滞磺,然后又找到了線程D升薯,發(fā)現(xiàn)線程D請求的鎖被線程A自己持有著。這時它就知道發(fā)生了死鎖击困。
    下面是一幅關(guān)于四個線程(A,B,C和D)之間鎖占有和請求的關(guān)系圖涎劈。像這樣的數(shù)據(jù)結(jié)構(gòu)就可以被用來檢測死鎖。

一個可行的做法是釋放所有鎖阅茶,回退责语,并且等待一段隨機的時間后重試。這個和簡單的加鎖超時類似目派,不一樣的是只有死鎖已經(jīng)發(fā)生了才回退,而不會是因為加鎖的請求超時了胁赢。雖然有回退和等待企蹭,但是如果有大量的線程競爭同一批鎖,它們還是會重復(fù)地死鎖(編者注:原因同超時類似智末,不能從根本上減輕競爭)谅摄。

一個更好的方案是給這些線程設(shè)置優(yōu)先級,讓一個(或幾個)線程回退系馆,剩下的線程就像沒發(fā)生死鎖一樣繼續(xù)保持著它們需要的鎖送漠。如果賦予這些線程的優(yōu)先級是固定不變的,同一批線程總是會擁有更高的優(yōu)先級由蘑。為避免這個問題闽寡,可以在死鎖發(fā)生的時候設(shè)置隨機的優(yōu)先級。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尼酿,一起剝皮案震驚了整個濱河市爷狈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裳擎,老刑警劉巖涎永,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡羡微,警方通過查閱死者的電腦和手機谷饿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妈倔,“玉大人博投,你說我怎么就攤上這事∑粞模” “怎么了贬堵?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長结洼。 經(jīng)常有香客問我黎做,道長,這世上最難降的妖魔是什么松忍? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任蒸殿,我火速辦了婚禮,結(jié)果婚禮上鸣峭,老公的妹妹穿的比我還像新娘宏所。我一直安慰自己,他們只是感情好摊溶,可當我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布爬骤。 她就那樣靜靜地躺著,像睡著了一般莫换。 火紅的嫁衣襯著肌膚如雪霞玄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天拉岁,我揣著相機與錄音坷剧,去河邊找鬼。 笑死喊暖,一個胖子當著我的面吹牛惫企,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陵叽,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼狞尔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了巩掺?” 一聲冷哼從身側(cè)響起沪么,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锌半,沒想到半個月后禽车,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寇漫,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年殉摔,在試婚紗的時候發(fā)現(xiàn)自己被綠了州胳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡逸月,死狀恐怖栓撞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碗硬,我是刑警寧澤瓤湘,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站恩尾,受9級特大地震影響弛说,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翰意,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一木人、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧冀偶,春花似錦醒第、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至客年,卻和暖如春霞幅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搀罢。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留侥猩,地道東北人榔至。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像欺劳,于是被迫代替她去往敵國和親唧取。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1划提、競態(tài)條件: 定義:競態(tài)條件指的是一種特殊的情況枫弟,在這種情況下各個執(zhí)行單元以一種沒有邏輯的順序執(zhí)行動作,從而導(dǎo)致...
    Hughman閱讀 1,296評論 0 7
  • 死鎖產(chǎn)生的原因和解鎖的方法 產(chǎn)生死鎖的四個必要條件: (1) 互斥條件:一個資源每次只能被一個進程使用鹏往。 (2) ...
    憩在河岸上的魚丶閱讀 1,487評論 0 4
  • 一淡诗、什么是死鎖 所謂死鎖,是指多個進程循環(huán)等待它方占有的資源而無限期地僵持下去的局面。 二韩容、產(chǎn)生死鎖的必要條件 互...
    Q南南南Q閱讀 774評論 0 0
  • 一群凶、死鎖的基本概念 1.1 死鎖的定義 一組進程中插爹,每個進程都無限等待被該組進程中另一進程所占用的資源,因而永遠無...
    yjaal閱讀 1,488評論 0 6
  • 自從開始搞微信公眾號吧请梢,就覺得自己找到了好玩的東西赠尾。可是每天要專門騰出時間來寫點東西毅弧,其實真的挺不容易的气嫁。于是偶爾...
    小狠莉莉閱讀 330評論 0 2