面試題之死鎖解密

尹吉歡發表於2018-07-09

死鎖的概念

在多執行緒環境中,我們經常會遇到多個執行緒訪問同一個共享資源的情況,這個時候必須考慮如何維護資料一致性,常見的方式是加鎖處理。只有拿到鎖的執行緒才可以訪問共享資源,通過鎖就可以讓執行緒對共享資源的訪問都是順序的,避免出現一些資料不一致的問題。

在使用鎖的過程中同樣也有風險,最為常見的就是死鎖現象。死鎖就相當於繩子打死結一樣,解不開了。在程式中出現這樣的情況往往是由於多個執行緒同時鎖住多個資源不釋放導致的。

編寫一個死鎖程式

public class Deadlock {
    public static String str1 = "str1";
    public static String str2 = "str2";

    public static void main(String[] args){
        Thread a = new Thread(() -> {
             try{
                 while(true){
                     synchronized(Deadlock.str1){
                         System.out.println(Thread.currentThread().getName()+"鎖住 str1");
                         Thread.sleep(1000);
                         synchronized(Deadlock.str2){
                             System.out.println(Thread.currentThread().getName()+"鎖住 str2");
                         }
                     }
                 }
             }catch(Exception e){
                 e.printStackTrace();
             }
        });

        Thread b = new Thread(() -> {
            try{
                while(true){
                    synchronized(Deadlock.str2){
                        System.out.println(Thread.currentThread().getName()+"鎖住 str2");
                        Thread.sleep(1000);
                        synchronized(Deadlock.str1){
                             System.out.println(Thread.currentThread().getName()+"鎖住 str1");
                        }
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        });

        a.start();
        b.start();
    }    
}

上面的程式碼就是一個完整的死鎖程式,程式中有兩個執行緒,執行緒1鎖住了str1,獲得鎖之後休眠1秒鐘,這個時候執行緒2鎖住了str2,也進行休眠操作。

執行緒1休眠完了之後去鎖str2,但是str2已經被執行緒2給鎖住了,這邊只能等待,同樣的道理,執行緒2休眠完之後也要去鎖str1,同樣也會等待,這樣死鎖就產生了。

如果我們將下面這2行程式碼的值改成一樣,死鎖還會存在嗎?

 public static String str1 = "str1";
 public static String str2 = "str1";

答案是不會,為什麼?
網上看到別人的回答:在宣告一個物件作為鎖的時候要注意字串型別鎖物件,因為字串有一個常量池,如果不同的執行緒持有的鎖是具有相同字元的字串鎖時,兩個鎖實際上同一個鎖。

如何檢視死鎖

首先程式不會往下執行了,這是直觀的能夠看到的死鎖現象,看不到的我們可以通過jstack PID檢視執行緒資訊,有死鎖的話在最下面會告訴我們檢測到了死鎖的存在,如下圖:

delock.png

關鍵資訊:Found one Java-level deadlock


高併發程式設計帶來的挑戰遠遠不止一個死鎖這麼簡單,還有很多未知的問題,想要深入的掌握非常不容易。

為了感覺大家一致以來的支援,也為了能夠讓大家學好高併發程式設計,特意贈送三本書籍來幫助大家學習。

Java高併發程式設計詳解:多執行緒與架構設計介紹

作者毫無保留地分享了多年的Java伺服器、大資料程式開發架構經驗和實踐。實戰性強,從底層原理的角度總結和歸納各個技術細節,結合真實的案例講解高併發程式設計架構的技巧。

適讀人群 :
- 1. 開發人員
他們可以非常系統地掌握Java多執行緒高併發的開發技巧和深入理解其中API的細節;
- 2. 架構師
他們可以掌握架構設計的技巧,搭建高吞吐量高可用的Java應用程式;
- 3. 關於Java技術的程式設計師

立足於執行緒原始碼剖析,從基礎入手,逐層漸進深入,環環緊扣,針對技術細節進行了細緻歸納,在解讀原始碼的時候又引入了優秀的架構設計。

以業務場景下的真實問題作為導向,詳細闡述每一個解決方案的來龍去脈,突出“身臨其境”的閱讀效果。

將大量的實際案例、原理剖析和實戰程式碼相結合,讓讀者能夠更加清晰深入地理解每一個技術細節的用法和實用技巧。

結合業界公認的好的設計架構技巧模式解決實際開發中遇到的問題,站在程式架構設計的角度指導讀者設計高效靈活的多執行緒應用程式。
Java高併發程式設計詳解:多執行緒與架構設計

活動規則

本次活動共3本書籍,下面說下本次的活動規則:

1. 加入猿天地純技術交流群,詳情檢視《大牛坐鎮|高階JAVA純技術群你要加入嗎?》
加入本群的朋友將有機會抽取其中一本書籍,目前群成員20人,中獎機率很高哦!

2. 關注本公眾號,回覆抽獎,掃描抽獎二維碼即可參與活動,13號晚上6點自動開獎,贈送1本。

3. 在本文章下面留言,說出你想學習的理由(必須走心,隨便說不會上牆),點贊數最高1位朋友中獎,贈送1本。點贊數統計也是截止到13號晚上6點。

猿天地

相關文章