什么是死鎖?
答:兩個或多個線程互相持有對方需要的鎖而導致這些線程全部處於永久阻塞狀態。如:線程A持有對象1的鎖,等待對象2的鎖;線程B持有對象2的鎖,等待對象1的鎖。
發生死鎖的四個必要條件:
1.互斥條件:對於訪問某些公共資源的線程需實現線程同步,即不能同時訪問。
2.不剝奪條件:未使用完不可強行剝奪
3.請求和保持條件:進程至少持有一個資源同時要請求新的資源。
4.環路等待條件:存在一個線程-資源環形鏈。在進程集合{p0,p1...pn}中,p0正在等待p1占用的資源,p1等待p2占用的資源...pn等待p0占用的資源。
死鎖的代碼實現:
public class DeadLock implements Runnable{ //注意,這里需要定義為static,否則t1和t2兩個線程中的o1,o2均為新創建的,也就是此o1非彼o1,o2也一樣,即不存在資源沖突,不會發生死鎖。字符串除外,因為有字符串池 private static Object o1=new Object(); private static Object o2=new Object(); private int flag; public DeadLock(int flag){ this.flag=flag; } @Override public void run() { if(flag==0){ synchronized (o1){ System.out.println("t1 Get the lock of o1"); try{ Thread.sleep(1000); } catch (InterruptedException ex){ ex.printStackTrace(); } synchronized (o2){ System.out.println("t1 Get the lock of o2"); } } } else{ synchronized (o2){ System.out.println("t2 Get the lock of o2"); try{ Thread.sleep(1000); } catch (InterruptedException ex){ ex.printStackTrace(); } synchronized (o1){ System.out.println("t2 Get the lock of o1"); } } } } public static void main(String[]args){ DeadLock D1=new DeadLock(0); DeadLock D2=new DeadLock(1); Thread t1=new Thread(D1); Thread t2=new Thread(D2); t1.start(); t2.start(); } }
解決死鎖的三種方案:
1.資源排序
如上訴代碼中將else{}中的o1和o2調換順序即可。
2.加鎖時限
如果一個線程沒有在指定的時間期限內獲取到鎖,則結束當前線程並釋放掉已獲得的鎖。終止線程的方法:stop()會釋放掉鎖但易導致數據不一致。suspend()終止線程但不會釋放掉鎖。
3.死鎖檢測
參考:線程死鎖的原理及解決方式