Java執行緒面試題(02) Java執行緒中如何避免死鎖
本文為本博主翻譯,未經允許,嚴禁轉載!
簡介
如何避免Java中的死鎖?是多執行緒程式設計常見問題之一,在高階別的面試中經常被問及,並帶來了大量的後續問題。儘管問題看起來很基本,但是一旦開始深入,大部分開發者都會陷入困境。
面試問題從“什麼是死鎖?”開始。答案很簡單,當有兩個或更多的執行緒在等待對方釋放鎖並無限期地卡住時,這種情況就稱為死鎖。這隻會發生在多執行緒的情況下。
Java中如何監測死鎖
雖然這可能有很多的答案,我的版本是首先我會看程式碼,如果我看到巢狀的同步塊或從其他呼叫一個同步方法或嘗試鎖定不同的物件,那麼如果開發人員不是非常小心,很有可能發生死鎖。
其他方法是在執行應用程式時實際上被鎖定的時候找到它,試著對執行緒進行轉儲,在Linux中你可以通過命令“kill -3”來做到這一點,這將在應用程式日誌檔案中列印所有執行緒的狀態,而你可以看到哪個執行緒被鎖定在哪個物件上。
其他的方法是使用jconsole,它會告訴你究竟哪個執行緒被鎖定在哪個物件上。
編寫一個會導致死鎖的Java程式
一旦你回答了這個問題,他們可能會要求你編寫會導致死鎖的程式碼?這是我的一個版本。
/**
* * Java program to create a deadlock by imposing circular wait. * * @author
* WINDOWS 8 *
*/
public class DeadLockDemo {
/*
* This method request two locks, first String and then Integer
**/
public void method1() {
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
}
}
}
/*
* * This method also requests same two lock but in exactly * Opposite order
* i.e. first Integer and then String. * This creates potential deadlock, if
* one thread holds String lock * and other holds Integer lock and they wait
* for each other, forever.
*/
public void method2() {
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
}
}
}
}
如果method1()和method2()都被兩個或多個執行緒呼叫,死鎖就很有可能,因為如果執行緒1在執行method1()時獲取對Sting物件的鎖,並且執行緒2在執行method2()時獲取對Integer物件的鎖, 那麼這兩個執行緒都將在等待對方釋放Integer和String鎖,這將永遠不會發生。這個圖完全展示了我們的程式,其中一個執行緒持有一個物件的鎖,並等待其他執行緒持有的其他物件鎖。
如何避免Java中的死鎖?
現在面試官來到最後一部分,我認為最重要的部分之一: 你如何解決死鎖?或者如何避免Java中的死鎖?
如果你仔細看過上面的程式碼,那麼你可能已經發現死鎖的真正原因並不是多執行緒,而是它們請求鎖定的方式,如果你提供了一個有序的訪問,那麼問題就會解決,這裡是我的修復死鎖問題的版本,它可以通過在沒有搶佔的情況下避免迴圈等待從而解決死鎖問題。
public class DeadLockFixed {
/**
* * Both method are now requesting lock in same order, first Integer and
* then String. * You could have also done reverse e.g. first String and
* then Integer, * both will solve the problem, as long as both method are
* requesting lock * in consistent order.
*/
public void method1() {
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
}
}
}
public void method2() {
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
}
}
}
}
現在不會有任何死鎖,因為兩個方法都以相同的順序訪問Integer和String類的鎖。因此,如果執行緒A獲得了Integer物件上的鎖,則執行緒B將不會繼續,直到執行緒A釋放Integer鎖定為止,即使執行緒B持有String鎖,執行緒A也不會被阻塞,因為現線上程B不會期望執行緒A釋放Integer鎖繼續前進。原文連結
相關文章
- Java多執行緒(五):死鎖Java執行緒
- java多執行緒(5)死鎖Java執行緒
- Java多執行緒中執行緒安全與鎖問題Java執行緒
- 【Java面試題】Java面試之多執行緒!Java面試題執行緒
- java多執行緒、集合和IO面試題_02Java執行緒面試題
- Java多執行緒(2)執行緒鎖Java執行緒
- 【JAVA】【面試】【基礎篇】- 執行緒、鎖Java面試執行緒
- java 執行緒淺解03[執行緒同步以及經典死鎖]Java執行緒
- Java執行緒面試題 Top 50Java執行緒面試題
- 執行緒中的死鎖執行緒
- 【Java面試】如何中斷一個正在執行的執行緒?Java面試執行緒
- Java面試題:執行緒池內“鬧情緒”的執行緒,怎麼辦?Java面試題執行緒
- Java多執行緒面試高配問題---多執行緒(3)🧵Java執行緒面試
- 如何處理執行緒死鎖執行緒
- JAVA CPU100%與執行緒死鎖定位Java執行緒
- Java併發--Java執行緒面試題 Top 50Java執行緒面試題
- Java常用面試題之Java多執行緒(十三)Java面試題執行緒
- 聊聊面試中的 Java 執行緒池面試Java執行緒
- #大學#Java多執行緒學習02(執行緒同步)Java執行緒
- java執行緒的筆試題Java執行緒筆試
- Java 執行緒安全 與 鎖Java執行緒
- 死磕 java執行緒系列之執行緒的生命週期Java執行緒
- java面試一日一題:java執行緒池Java面試執行緒
- JAVA多執行緒詳解(3)執行緒同步和鎖Java執行緒
- Java面試經典題:執行緒池專題Java面試執行緒
- 面試官:Java 執行緒如何啟動的?面試Java執行緒
- Java多執行緒-執行緒中止Java執行緒
- 阿里一面:Java中如何停止執行緒?阿里Java執行緒
- 史上最全 Java 多執行緒面試題及答案Java執行緒面試題
- 精選30道Java多執行緒面試題Java執行緒面試題
- 史上最全Java多執行緒面試題,附答案Java執行緒面試題
- Java中的執行緒Java執行緒
- Java多執行緒之執行緒中止Java執行緒
- Java多執行緒-執行緒狀態Java執行緒
- Java多執行緒-執行緒通訊Java執行緒
- java 多執行緒守護執行緒Java執行緒
- java多執行緒9:執行緒池Java執行緒
- 【java多執行緒】(二)執行緒停止Java執行緒
- java執行緒執行緒休眠,sleep方法Java執行緒