java如何避免程式死鎖
併發程式一旦死鎖,往往我們只能重啟應用。解決死鎖問題最好的辦法就是避免死鎖。
死鎖發生的條件
互斥,共享資源只能被一個執行緒佔用
佔有且等待,執行緒 t1 已經取得共享資源 s1,嘗試獲取共享資源 s2 的時候,不釋放共享資源 s1
不可搶佔,其他執行緒不能強行搶佔執行緒 t1 佔有的資源 s1
迴圈等待,執行緒 t1 等待執行緒 t2 佔有的資源,執行緒 t2 等待執行緒 t1 佔有的資源
避免死鎖的方法
對於以上 4 個條件,只要破壞其中一個條件,就可以避免死鎖的發生。
對於第一個條件 "互斥" 是不能破壞的,因為加鎖就是為了保證互斥。
其他三個條件,我們可以嘗試
一次性申請所有的資源,破壞 "佔有且等待" 條件
佔有部分資源的執行緒進一步申請其他資源時,如果申請不到,主動釋放它佔有的資源,破壞 "不可搶佔" 條件
按序申請資源,破壞 "迴圈等待" 條件
使用管理類一次性申請所有的資源,破壞 "佔有且等待" 條件示例
package constxiong.concurrency.a023;
import java.util.HashSet;
import java.util.Set;
/**
* 測試 一次性申請所有的資源,破壞 "佔有且等待" 條件示例
* @author ConstXiong
* @date 2019-09-24 14:04:12
*/
public class TestBreakLockAndWait {
//單例的資源管理類
private final static Manger manager = new Manger();
//資源1
private static Object res1 = new Object();
//資源2
private static Object res2 = new Object();
public static void main(String[] args) {
new Thread(() -> {
boolean applySuccess = false;
while (!applySuccess) {
//向管理類,申請res1和res2,申請失敗,重試
applySuccess = manager.applyResources(res1, res2);
if (applySuccess) {
try {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 申請 res1、res2 資源成功");
synchronized (res1) {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 獲取到 res1 資源的鎖");
//休眠 1秒
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (res2) {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 獲取到 res2 資源的鎖");
}
}
} finally {
manager.returnResources(res1, res2);//歸還資源
}
} else {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 申請 res1、res2 資源失敗");
//申請失敗休眠 200 毫秒後重試
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(() -> {
boolean applySuccess = false;
while (!applySuccess) {
//向管理類,申請res1和res2,申請失敗,重試
applySuccess = manager.applyResources(res1, res2);
if (applySuccess) {
try { 無錫婦科醫院哪家好
System.out.println("執行緒:" + Thread.currentThread().getName() + " 申請 res1、res2 資源成功");
synchronized (res2) {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 獲取到 res1 資源的鎖");
//休眠 1秒
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (res1) {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 獲取到 res2 資源的鎖");
}
}
} finally {
manager.returnResources(res1, res2);//歸還資源
}
} else {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 申請 res1、res2 資源失敗");
//申請失敗休眠 200 毫秒後重試
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
}
/**
* 資源申請、歸還管理類
* @author ConstXiong
* @date 2019-09-24 14:10:57
*/
class Manger {
//資源存放集合
private Set
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2658352/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [Java併發]避免死鎖Java
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- Java執行緒面試題(02) Java執行緒中如何避免死鎖Java執行緒面試題
- 面試官:什麼是死鎖?怎麼排查死鎖?怎麼避免死鎖?面試
- Java鎖——死鎖Java
- 如何通過程式設計發現Java死鎖程式設計Java
- fmdb中databasequeue的使用,避免死鎖Database
- 殺死Oracle死鎖程式Oracle
- java中避免集合死鏈呼叫Java
- 什麼是死鎖?如何解決死鎖?
- 例項詳解 Java 死鎖與破解死鎖Java
- 作業系統(5) 死鎖的概念 死鎖產生的必要條件 死鎖的處理策略 預防死鎖 避免死鎖 死鎖的檢測和解除 銀行家演算法作業系統演算法
- 阿里二面:如何定位&避免死鎖?連著兩個面試問到了!阿里面試
- Java 中的死鎖Java
- 如何寫一段死鎖程式碼
- 檢視oracle死鎖程式並結束死鎖Oracle
- java程式設計思想之併發(死鎖)Java程式設計
- Java併發程式設計實戰(4)- 死鎖Java程式設計
- Java 程式死鎖問題原理及解決方案Java
- Mysql如何處理死鎖MySql
- java中死鎖是什麼Java
- Java 併發程式設計:如何防止線上程阻塞與喚醒時死鎖Java程式設計
- 殺掉鎖死的程式
- MySQL InnoDB如何應付死鎖MySql
- [C#.NET 拾遺補漏]12:死鎖和活鎖的發生及避免C#
- Java中常見死鎖與活鎖的例項Java
- Java多執行緒(五):死鎖Java執行緒
- java多執行緒(5)死鎖Java執行緒
- Java多執行緒7:死鎖Java執行緒
- Java 實現執行緒死鎖Java執行緒
- 完全乾掉Oracle死鎖程式Oracle
- oracle殺死鎖表的程式Oracle
- 【sqlserver】殺掉所有死鎖程式SQLServer
- 死鎖
- SQ死鎖及死鎖的解決
- 實戰:併發轉賬業務中避免死鎖的各種方法
- 如何處理執行緒死鎖執行緒
- 【MySQL】如何閱讀死鎖日誌MySql