<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一種死鎖的情況……

          共 1935字,需瀏覽 4分鐘

           ·

          2021-12-23 09:31

          前言

          在多線程編程的時候,為了確保同一時間數(shù)據(jù)狀態(tài)的唯一性,我們經(jīng)常會用到鎖(lock),它用起來很方便也很簡單,但是在某些特定的應(yīng)用場景之下,它會給你帶來很多困惑,,比如死鎖的情況,今天我們就來通過一段簡單的代碼,來看下什么是死鎖,以及如何避免死鎖。

          死鎖

          我們通過一段代碼來模擬下死鎖的情況:

          public?class?Example?{
          ????private?static?String?a?=?"a";
          ????private?static?String?b?=?"b";

          ????public?static?void?main(String[]?args)?{
          ????????new?Example().deadLock();
          ????}

          ????private?void?deadLock()?{
          ????????Thread?t1?=?new?Thread(()?->?{
          ????????????synchronized?(a)?{
          ????????????????try?{
          ????????????????????Thread.currentThread().sleep(2000);
          ????????????????}?catch?(Exception?e)?{
          ????????????????????e.printStackTrace();
          ????????????????}
          ????????????????synchronized?(b)?{
          ????????????????????System.out.println("b1");
          ????????????????}
          ????????????}
          ????????});

          ????????Thread?t2?=?new?Thread(()?->?{
          ????????????synchronized?(b)?{
          ????????????????synchronized?(a)?{
          ????????????????????System.out.println("a2");
          ????????????????}
          ????????????}
          ????????});
          ????????t1.start();
          ????????t2.start();
          ????}

          }

          上面的代碼中,我們定義了兩個static變量,在deadLock方法內(nèi),分別定義了兩個線程,在第一個線程內(nèi),我們通過synchronized關(guān)鍵字分別對變量ab加鎖,b鎖位于a鎖內(nèi)部,在獲取b資源前,先休眠2秒;在第二個線程內(nèi),我們也是通過synchronized關(guān)鍵字分別對ba進行加鎖,a鎖位于b鎖內(nèi),但是沒有睡眠。

          上面兩個線程,運行順序是這樣的:

          如果是t1先啟動,t1線程啟動后會先對a資源加鎖,之后t1休眠2秒,在在線程t1啟動到休眠結(jié)束這段時間中,t2線程啟動并對b資源加鎖,并嘗試獲取a的鎖,但由于a已經(jīng)被t1加鎖且未釋放鎖,這時候t2開始等待t1釋放資源,一直到t1休眠結(jié)束也未獲取到資源,這時候t1開始嘗試獲取b資源的鎖,但由于b資源被t2占用,所以t1也必須等待,最終的結(jié)果是兩個線程都在等待對方釋放資源,兩個線程都被阻塞,導致死鎖。

          t2先啟動的情況,實際測試中沒法復現(xiàn),但如果把t2放在t1前面start,那是不會導致死鎖的,t2執(zhí)行完很快就釋放資源了,所以不會導致線程阻塞,但如果加了睡眠時間,就和t1先啟動的情況一樣了。

          不喜歡看文字的小伙伴,可以看這個時序圖,很直觀地體現(xiàn)了死鎖的情況:

          如何避免死鎖

          既然知道了導致死鎖的原因,我們應(yīng)該如何避免這種情況出現(xiàn)呢?

          第一個解決方法——戒貪,簡單來說,就是盡量避免一個線程獲取多個鎖的情況,如果只是對一個資源加鎖的話,那自然是不會導致死鎖情況出現(xiàn)的;

          第二解決方法,就是引入超時機制,也就是采用定時鎖,使用lock.tryLock(timeout)替換synchronized

          對于,數(shù)據(jù)庫鎖,加鎖和解鎖必須在同一個數(shù)據(jù)庫連接中進行,否則會出現(xiàn)解鎖失敗的情況。

          總結(jié)

          鎖是多線程編程中一個特別有效的工具,很方便,也解決了資源共享的數(shù)據(jù)同步問題,但如何用好這個工具就是門藝術(shù)了,總之一句話就是要多學習,多實踐,不斷試錯,除此之外,沒有其他的捷徑了。

          多線程這塊的知識,想要學好學精,不僅要了解jvm的相關(guān)知識,還要熟悉處理器層面的知識,山高路遠,還得加油呀!

          好了,今天就到這里吧

          - END -


          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  8x8x最新网址 | 操逼爽视频 | 欧美大黄视频 | 中文字幕亚洲乱伦 | 亚洲黄色电影怎么 |