java线程如何避免死锁_Java面试问题,如何避免Java线程中的死锁?
如何避免Java中的死鎖?是流行的Java面試問題之一,也是多線程的流行話題之一。盡管問題看起來很簡單,但是一旦深入,大多數Java開發人員就會陷入困境。
面試問題以“什么是死鎖?”當兩個或多個線程正在等待彼此釋放所需資源(鎖定)并陷入無限時間的阻塞時,這種情況稱為死鎖,它只會在多任務或多線程的情況下發生。
如何檢測Java中的死鎖?
雖然這可能有很多答案,但我的版本是,如果我看到嵌套的同步塊,或者從其他同步方法調用一個同步方法,或者試圖在不同的對象上獲得鎖,那么如果開發人員不是非常小心,就很可能出現死鎖。
另一種方法是在運行應用程序時發現線程被鎖定,嘗試使用線程轉儲,在Linux中可以通過命令“kill -3”來實現,這將打印應用程序日志文件中所有線程的狀態,就可以看到哪個線程被鎖定在哪個對象上。
也可以使用fastthread等工具分析線程轉儲,上傳你的線程轉儲并分析它。
另一種方法是使用jConsole/VisualVM,它將準確地顯示哪些線程被鎖定,以及在哪個對象上。
編寫一個會導致死鎖的Java程序
一旦回答了前面的問題,他們可能會要求你編寫導致Java死鎖的代碼
這是我的一個版本
/**
* Java程序通過強制循環等待來創建死鎖
*
* @author WINDOWS 8
*
*/
public class DeadLockDemo {
/*
* T此方法請求兩個鎖,首先是String,然后是Integer
*/
public void method1() {
synchronized (String.class) {
System.out.println("Aquired lock onString.classobject");
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
}
}
}
/* * 此方法也請求相同的兩個鎖
* 順序相反,先整型,然后是字符串
* 如果一個線程持有字符串鎖,則會產生潛在的死鎖
* 另一個持有整數鎖,它們會一直等待對方
*/
public void method2() {
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.classobject");
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
}
}
}
}
如果method1()和method2()都將被兩個或多個線程調用,那么死鎖的可能性很大,如果線程1在執行method1()時獲取Sting對象上的鎖,而線程2在執行method2()時獲取Integer對象上的鎖,那么線程2將等待對方釋放Integer和String上的鎖以繼續執行,而這永遠不會發生
此圖準確演示了我們的程序,其中一個線程持有一個對象的鎖并等待其他線程持有的其他對象鎖。
這個圖展示了我們的這個程序,一個線程持有一個對象的鎖,等待另一個線程持有的其他對象鎖。
你可以看到線程1想要對線程2持有的對象2的鎖定,而線程2想要對線程1持有的對象1進行鎖定。由于沒有線程愿意放棄,所以存在死鎖并且Java程序卡住了。
如何避免Java中的死鎖
現在面試官來到最后一部分,這是我認為最重要的部分之一; 你如何修復代碼中的死鎖?或者如何避免Java中的死鎖?
如果仔細查看了上面的代碼,那么你可能已經發現死鎖的真正原因不是多線程,而是它們請求鎖定的方式,如果提供有序訪問,則問題將得到解決。
這是我的固定版本,它避免了由于沒有搶占的無效循環等待導致的死鎖,這是需要死鎖的四個條件之一。
public class DeadLockFixed {
/**
* 兩種方法現在都以相同的順序請求鎖定,首先是Integer,然后是String。
* 也可以完成反向,例如第一個String然后是Integer
* 兩者都會解決問題,只要兩種方法都請求鎖定
* 按照一致的順序
*/
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釋放整數鎖定,同樣,即使線程B保持字符串鎖定,線程A也不會被阻止,因為現在線程B不會期望線程A釋放整數鎖定繼續進行。
總結
以上是生活随笔為你收集整理的java线程如何避免死锁_Java面试问题,如何避免Java线程中的死锁?的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 李宏毅机器学习(七)GPT的野望
- 下一篇: potainer 日志_日志系统落地:制
