Java同步機(jī)制之死鎖

Java并發(fā)系列番外篇——同步機(jī)制(三)

姊妹篇《Java同步機(jī)制之synchronized
姊妹篇《Java同步機(jī)制之volatile

指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過程中,因爭奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用份殿,它們都將無法推進(jìn)下去巫延。

先來看一則新聞:

《武器貿(mào)易條約》是聯(lián)合國為監(jiān)管八類常規(guī)武器的國際貿(mào)易制定的共同國際標(biāo)準(zhǔn),該條約于2013年4月2日在聯(lián)合國大會(huì)上通過掌呜。2013年6月3日在紐約聯(lián)合國總部開放供所有國家簽署,當(dāng)天簽署的國家超過60個(gè)。不過紧卒,美國、中國和俄羅斯這3個(gè)安理會(huì)常任理事國當(dāng)天沒有簽約诗祸。后來跑芳,最大武器生產(chǎn)和出口國美國簽署該條約,但未正式批準(zhǔn)直颅。中國和俄羅斯還未簽署這一條約博个。2019年4月26日,美國總統(tǒng)特朗普在印第安納州舉行的美國步槍協(xié)會(huì)年會(huì)上宣布功偿,《武器貿(mào)易條約》是一個(gè)“嚴(yán)重誤導(dǎo)的條約”盆佣,美國將撤銷在該條約上的簽字。特朗普將要求國會(huì)參議院停止該條約的批準(zhǔn)程序械荷,使美國退出聯(lián)合國《武器貿(mào)易條約》共耍。

其實(shí)是這樣的:
美國:我等俄羅斯先簽了我就簽;
俄羅斯:我等中國先簽我了就簽养葵;
中國:我等美國先簽了我就簽征堪;


image

算了,不等了关拒。因?yàn)樗梨i了佃蚜。

代碼示例

當(dāng)一個(gè)線程永遠(yuǎn)的持有一個(gè)鎖,并且其他線程線程都嘗試獲得鎖時(shí)着绊,那么它們將永遠(yuǎn)被阻塞谐算。在線程A持有鎖a并且想獲得鎖b時(shí),線程B持有鎖b并嘗試獲得a時(shí)归露,那么這兩個(gè)線程將永遠(yuǎn)的等待下去洲脂。這種情況就是最簡單的死鎖形式:

public class TestDead {
    private Object a;
    private Object b;

    public TestDead(Object a, Object b) {

        this.a = a;
        this.b = b;
    }

    public void funOne(){
        synchronized (a){
            System.out.println("finOne");
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            funTwo();
        }
    }
    public void funTwo(){
        synchronized (b){
            System.out.println("finTwo");
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            funOne();
        }
    }

}

TestDead testDead = new TestDead(new Object(), new Object());
new Thread(new Runnable() {
            @Override
            public void run() {
                testDead.funOne();
            }
        }).start();
new Thread(new Runnable() {
            @Override
            public void run() {
                testDead.funTwo();
            }
        }).start();

程序的運(yùn)行結(jié)果如下:


image

上面的代碼會(huì)造成線程的假死,在沒有外力作用下。兩個(gè)線程會(huì)永遠(yuǎn)處于阻塞的狀態(tài)恐锦,等待一把永遠(yuǎn)不可以釋放的鎖往果。

產(chǎn)生死鎖的必要條件

  • 互斥條件:指進(jìn)程對(duì)所分配到的資源進(jìn)行排它性使用,即在一段時(shí)間內(nèi)某資源只由一個(gè)進(jìn)程占用一铅。如果此時(shí)還有其它進(jìn)程請(qǐng)求資源陕贮,則請(qǐng)求者只能等待,直至占有資源的進(jìn)程用畢釋放潘飘。
  • 占有且等待:指進(jìn)程已經(jīng)保持至少一個(gè)資源肮之,但又提出了新的資源請(qǐng)求,而該資源已被其它進(jìn)程占有卜录,此時(shí)請(qǐng)求進(jìn)程阻塞戈擒,但又對(duì)自己已獲得的其它資源保持不放。
  • 不可強(qiáng)行占有:指進(jìn)程已獲得的資源艰毒,在未使用完之前筐高,不能被剝奪,只能在使用完時(shí)由自己釋放丑瞧。
  • 循環(huán)等待條件:指在發(fā)生死鎖時(shí)凯傲,必然存在一個(gè)進(jìn)程——資源的環(huán)形鏈,即進(jìn)程集合{P0嗦篱,P1,P2幌缝,···灸促,Pn}中的P0正在等待一個(gè)P1占用的資源;P1正在等待P2占用的資源涵卵,……浴栽,Pn正在等待已被P0占用的資源。

<u>這四個(gè)條件是死鎖的必要條件轿偎,只要系統(tǒng)發(fā)生死鎖典鸡,這些條件必然成立,而只要上述條件之一不滿足坏晦,就不會(huì)發(fā)生死鎖萝玷。</u>

死鎖的避免與診斷

與許多其他并發(fā)危險(xiǎn)一樣,死鎖造成的影響很少會(huì)立刻呈現(xiàn)出來昆婿。如果一個(gè)類可能發(fā)生死鎖球碉,并不意味這每次都會(huì)發(fā)生死鎖,而是只表示有可能仓蛆。當(dāng)死鎖發(fā)生時(shí)睁冬,往往是在最糟糕的時(shí)刻——在高負(fù)載情況下。
上文中的代碼鎖產(chǎn)生的死鎖可以通過查看是否存在嵌套的鎖獲取操作來檢查是否存在死鎖的可能看疙。但有時(shí)候獲取多個(gè)鎖的操作并不會(huì)這么明顯豆拨。

要避免出現(xiàn)死鎖的問題直奋,只需要破壞四個(gè)條件中的任何一個(gè)就可以了:

  • 打破互斥條件。即允許進(jìn)程同時(shí)訪問某些資源施禾。當(dāng)然脚线,這種方法試用范圍并不廣,因?yàn)橛械馁Y源不允許并發(fā)訪問拾积,或者存在線程安全問題殉挽。
  • 打破占有且等待條件⊥厍桑可以通過規(guī)定在任何情況下斯碌,一個(gè)線程獲取一個(gè)鎖之后,必須歸還了鎖之后才能請(qǐng)求另一鎖
  • 打破不可搶占條件肛度。除非線程自己還鑰匙傻唾,否則線程會(huì)一直占有鑰匙,是形成不可搶占條件的原因承耿。允許進(jìn)程強(qiáng)行從占有者那里奪取某些資源冠骄。就是說,當(dāng)一個(gè)進(jìn)程已占有了某些資源加袋,它又申請(qǐng)新的資源凛辣,但不能立即被滿足時(shí),它必須釋放所占有的全部資源职烧,以后再重新申請(qǐng)扁誓。
  • 打破循環(huán)等待條件。采用這種策略蚀之,即把資源事先分類編號(hào)蝗敢,按號(hào)分配,可以強(qiáng)制規(guī)定任何線程取鎖的順序足删。

其他活躍性危險(xiǎn)

盡管死鎖是最常見的活躍性危險(xiǎn)寿谴,但在并發(fā)中還存在一些其他的活躍性危險(xiǎn),包括:饑餓失受、活鎖等

饑餓:當(dāng)線程由于無法訪問它所需要的資源而不能繼續(xù)執(zhí)行時(shí)讶泰,就發(fā)生了饑餓。最常見的引發(fā)饑餓的資源就是CPU的時(shí)鐘周期拂到。
如果對(duì)線程的優(yōu)先級(jí)使用不當(dāng)峻厚,或者在持有鎖時(shí)進(jìn)行一些無法結(jié)束的操作(無限循環(huán)),就有可能產(chǎn)生饑餓谆焊,因?yàn)槠渌枰@個(gè)鎖的線程永遠(yuǎn)無法得到它惠桃。

活鎖:我為它賦予了一個(gè)充滿神話色彩的名字西西弗斯鎖西西弗斯神話
這是另一種形式的活躍性問題,盡管它不會(huì)阻塞線程辜王,但也不能繼續(xù)向下執(zhí)行劈狐,因?yàn)榫€程將不斷重復(fù)執(zhí)行相同的操作,而且總會(huì)失敗呐馆。
當(dāng)多個(gè)相互協(xié)作的線程都對(duì)彼此進(jìn)行響應(yīng)從而修改各自狀態(tài)肥缔,并使任何一個(gè)線程都無法執(zhí)行時(shí),就會(huì)發(fā)生活鎖汹来。
活鎖通常發(fā)生在處理事務(wù)的代碼中:如果不能成功的處理某個(gè)消息续膳,那么消息處理機(jī)制將回滾整個(gè)事務(wù),并將它重新放置在隊(duì)列的開頭收班。因此坟岔,處理事務(wù)的代碼將被反復(fù)調(diào)用,并返回相同的錯(cuò)誤結(jié)果摔桦,雖然處理消息的線程沒有被阻塞社付,但也無法執(zhí)行下去。

小結(jié)

死鎖(以及其他活躍性問題)是一個(gè)非常嚴(yán)重的問題邻耕,因?yàn)楫?dāng)它出現(xiàn)的時(shí)候鸥咖,除了中止應(yīng)用程序之外沒有其他任何方法可以修復(fù)這種故障。在設(shè)計(jì)時(shí)應(yīng)確保線程在獲取多個(gè)鎖時(shí)采用一致性的順序兄世。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啼辣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子御滩,更是在濱河造成了極大的恐慌熙兔,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艾恼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡麸锉,警方通過查閱死者的電腦和手機(jī)钠绍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來花沉,“玉大人柳爽,你說我怎么就攤上這事〖钇ǎ” “怎么了磷脯?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長娩脾。 經(jīng)常有香客問我赵誓,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任俩功,我火速辦了婚禮幻枉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诡蜓。我一直安慰自己熬甫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布蔓罚。 她就那樣靜靜地躺著椿肩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪豺谈。 梳的紋絲不亂的頭發(fā)上郑象,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音核无,去河邊找鬼扣唱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛团南,可吹牛的內(nèi)容都是我干的噪沙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼吐根,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼正歼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拷橘,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤局义,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后冗疮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體萄唇,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年术幔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了另萤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诅挑,死狀恐怖四敞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拔妥,我是刑警寧澤忿危,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站没龙,受9級(jí)特大地震影響铺厨,放射性物質(zhì)發(fā)生泄漏缎玫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一努释、第九天 我趴在偏房一處隱蔽的房頂上張望碘梢。 院中可真熱鬧,春花似錦伐蒂、人聲如沸煞躬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恩沛。三九已至,卻和暖如春缕减,著一層夾襖步出監(jiān)牢的瞬間雷客,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工桥狡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留搅裙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓裹芝,卻偏偏與公主長得像部逮,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嫂易,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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