一個死鎖的例子倒庵、死鎖的條件褒墨、如何避免死鎖

一、什么是死鎖

死鎖不僅在個人學(xué)習中擎宝,甚至在開發(fā)中也并不常見郁妈。但是一旦出現(xiàn)死鎖,后果將非常嚴重绍申。
首先什么是死鎖呢噩咪?打個比方顾彰,就好像有兩個人打架,互相限制住了(鎖住胃碾,抱住)彼此一樣涨享,互相動彈不得,而且互相歐氣仆百,你不松手我就不松手厕隧。好了誰也動彈不得。
在多線程的環(huán)境下俄周,勢必會對資源進行搶奪吁讨。當兩個線程鎖住了當前資源,但都需要對方的資源才能進行下一步操作峦朗,這個時候兩方就會一直等待對方的資源釋放建丧。這就形成了死鎖。這些永遠在互相等待的進程稱為死鎖進程波势。

那么我們來總結(jié)一下死鎖產(chǎn)生的條件:

互斥:資源的鎖是排他性的茶鹃,加鎖期間只能有一個線程擁有該資源。其他線程只能等待鎖釋放才能嘗試獲取該資源艰亮。
請求和保持:當前線程已經(jīng)擁有至少一個資源闭翩,但其同時又發(fā)出新的資源請求,而被請求的資源被其他線程擁有迄埃。此時進入保持當前資源并等待下個資源的狀態(tài)疗韵。
不剝奪:線程已擁有的資源,只能由自己釋放侄非,不能被其他線程剝奪蕉汪。
循環(huán)等待:是指有多個線程互相的請求對方的資源泵督,但同時擁有對方下一步所需的資源绽族。形成一種循環(huán),類似2)請求和保持阔籽。但此處指多個線程的關(guān)系叠赦。并不是指單個線程一直在循環(huán)中等待驹马。
什么?還是不理解除秀?那我們直接上代碼糯累,動手寫一個死鎖。

二册踩、寫一個死鎖

根據(jù)條件泳姐,我們讓兩個線程互相請求保持。

/**
 * 模擬死鎖場景
 */
public class DeadLockDemo implements Runnable{

    public static int flag = 1;

    //static 變量是 類對象共享的
    static Object o1 = new Object();
    static Object o2 = new Object();

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":此時 flag = " + flag);
        if(flag == 1){
            synchronized (o1){
                try {
                    System.out.println("我是" + Thread.currentThread().getName() + "鎖住 o1");
                    Thread.sleep(3000);
                    System.out.println(Thread.currentThread().getName() + "醒來->準備獲取 o2");
                }catch (Exception e){
                    e.printStackTrace();
                }
                synchronized (o2){
                    System.out.println(Thread.currentThread().getName() + "拿到 o2");//第24行
                }
            }
        }
        if(flag == 0){
            synchronized (o2){
                try {
                    System.out.println("我是" + Thread.currentThread().getName() + "鎖住 o2");
                    Thread.sleep(3000);
                    System.out.println(Thread.currentThread().getName() + "醒來->準備獲取 o1");
                }catch (Exception e){
                    e.printStackTrace();
                }
                synchronized (o1){
                    System.out.println(Thread.currentThread().getName() + "拿到 o1");//第38行
                }
            }
        }
    }

    public static  void main(String args[]){

        DeadLockDemo t1 = new DeadLockDemo();
        DeadLockDemo t2 = new DeadLockDemo();
        t1.flag = 1;
        new Thread(t1).start();

        //讓main線程休眠1秒鐘,保證t2開啟鎖住o2.進入死鎖
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t2.flag = 0;
        new Thread(t2).start();
    }

代碼中暂吉,
t1創(chuàng)建胖秒,t1先拿到o1的鎖缎患,開始休眠3秒。然后
t2線程創(chuàng)建阎肝,t2拿到o2的鎖挤渔,開始休眠3秒。然后
t1先醒來盗痒,準備拿o2的鎖蚂蕴,發(fā)現(xiàn)o2已經(jīng)加鎖,只能等待o2的鎖釋放俯邓。
t2后醒來骡楼,準備拿o1的鎖,發(fā)現(xiàn)o1已經(jīng)加鎖稽鞭,只能等待o1的鎖釋放鸟整。
t1,t2形成死鎖。

我們查看運行狀態(tài)


image.png

三朦蕴、發(fā)現(xiàn)排查死鎖情況

我們利用jdk提供的工具定位死鎖問題:

jps顯示所有當前Java虛擬機進程名及pid.
jstack打印進程堆棧信息篮条。


image.png

列出所有java進程。
我們檢查一下DeadLockDemo吩抓,為什么這個線程不退棧涉茧。

jstack 11170
image.png

我們直接翻到最后:已經(jīng)檢測出了一個java級別死鎖。其中兩個線程分別卡在了代碼第27行和第41行疹娶。檢查我們代碼的對應(yīng)位置伴栓,即可排查錯誤。此處我們是第二個鎖始終拿不到雨饺,所以死鎖了钳垮。

四、解決辦法

死鎖一旦發(fā)生额港,我們就無法解決了饺窿。所以我們只能避免死鎖的發(fā)生。
既然死鎖需要滿足四種條件移斩,那我們就從條件下手肚医,只要打破任意規(guī)則即可。

(互斥)盡量少用互斥鎖叹哭,能加讀鎖忍宋,不加寫鎖。當然這條無法避免风罩。
(請求和保持)采用資源靜態(tài)分配策略(進程資源靜態(tài)分配方式是指一個進程在建立時就分配了它需要的全部資源).我們盡量不讓線程同時去請求多個鎖,或者在擁有一個鎖又請求不到下個鎖時舵稠,不保持等待超升,先釋放資源等待一段時間在重新請求入宦。
(不剝奪)允許進程剝奪使用其他進程占有的資源。優(yōu)先級室琢。
(循環(huán)等待)盡量調(diào)整獲得鎖的順序乾闰,不發(fā)生嵌套資源請求。加入超時盈滴。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涯肩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子巢钓,更是在濱河造成了極大的恐慌病苗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件症汹,死亡現(xiàn)場離奇詭異硫朦,居然都是意外死亡,警方通過查閱死者的電腦和手機背镇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門咬展,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瞒斩,你說我怎么就攤上這事破婆。” “怎么了胸囱?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵祷舀,是天一觀的道長。 經(jīng)常有香客問我旺矾,道長蔑鹦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任箕宙,我火速辦了婚禮嚎朽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘柬帕。我一直安慰自己哟忍,他們只是感情好,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布陷寝。 她就那樣靜靜地躺著锅很,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凤跑。 梳的紋絲不亂的頭發(fā)上爆安,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音仔引,去河邊找鬼扔仓。 笑死褐奥,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的翘簇。 我是一名探鬼主播撬码,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼版保!你這毒婦竟也來了呜笑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤彻犁,失蹤者是張志新(化名)和其女友劉穎叫胁,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袖裕,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡曹抬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了急鳄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谤民。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖疾宏,靈堂內(nèi)的尸體忽然破棺而出张足,到底是詐尸還是另有隱情,我是刑警寧澤坎藐,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布为牍,位于F島的核電站,受9級特大地震影響岩馍,放射性物質(zhì)發(fā)生泄漏碉咆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一蛀恩、第九天 我趴在偏房一處隱蔽的房頂上張望疫铜。 院中可真熱鬧,春花似錦双谆、人聲如沸壳咕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谓厘。三九已至,卻和暖如春寸谜,著一層夾襖步出監(jiān)牢的瞬間竟稳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留住练,地道東北人地啰。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓愁拭,卻偏偏與公主長得像讲逛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子岭埠,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

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