<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>

          每日一例 | ?一種死鎖的情況……

          共 3776字,需瀏覽 8分鐘

           ·

          2021-05-28 14:03

          前言

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

          死鎖

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

          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)了死鎖的情況:

          如何避免死鎖

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

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

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

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

          總結(jié)

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

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

          好了,今天就到這里吧

          - END -


          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  伊人91在线 | 人人澡人人舔 | www.人人操.com | 操xxx操xxx | 亚洲欧美毛片高清 |