什麼是死鎖
- 死鎖是程序死鎖的簡稱
- 死鎖是指兩個或兩個以上的程序在執行過程中,由于競争資源或者由于彼此通信而造成的一種阻塞的現象,若無外力作用,它們都将無法推進下去。此時稱系統處于死鎖狀态或系統産生了死鎖,這些永遠在互相等待的程序稱為死鎖程序
- 簡單的說就是兩個或多個線程,等待對方釋放某個資源而卡死的情況稱之為死鎖
- 如下圖,就是死鎖的一種典型的情形
死鎖産生的必要條件
- 互斥使用,即當資源被一個線程使用(占有)時,别的線程不能使用
- 不可搶占,資源請求者不能強制從資源占有者手中奪取資源,資源隻能由資源占有者主動釋放。
- 請求和保持,即當資源請求者在請求其他的資源的同時保持對原有資源的占有。
- 循環等待,即存在一個等待隊列:P1占有P2的資源,P2占有P3的資源,P3占有P1的資源。這樣就形成了一個等待環路
典型死鎖代碼示例
public class LockTest {
public static String obj1 = "obj1";
public static String obj2 = "obj2";
public static void main(String[] args) {
LockA la = new LockA();
LockB lb = new LockB();
new Thread(la).start();
new Thread(lb).start();
}
static class LockA implements Runnable {
public void run() {
try {
System.out.println(System.nanoTime() + " LockA 開始執行");
while (true) {
synchronized (LockTest.obj1) {
System.out.println(System.nanoTime() + " LockA 鎖住 obj1");
Thread.sleep(); // 此處等待是給B能鎖住機會
synchronized (LockTest.obj2) {
System.out.println(System.nanoTime() + " LockA 鎖住 obj2");
Thread.sleep( * ); // 為測試,占用了就不放
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
static class LockB implements Runnable {
public void run() {
try {
System.out.println(System.nanoTime() + " LockB 開始執行");
while (true) {
synchronized (LockTest.obj2) {
System.out.println(System.nanoTime() + " LockB 鎖住 obj2");
Thread.sleep(); // 此處等待是給A能鎖住機會
synchronized (LockTest.obj1) {
System.out.println(System.nanoTime() + " LockB 鎖住 obj1");
Thread.sleep( * ); // 為測試,占用了就不放
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
- 輸出結果
22236254302964 LockA 開始執行
22236254398757 LockB 開始執行
22236254515387 LockA 鎖住 obj1
22236254560174 LockB 鎖住 obj2
怎樣避免死鎖
- 加鎖順序
- 加鎖時限
-
死鎖檢測
詳情見http://ifeve.com/deadlock-prevention/
另外的方法
- 盡量使用tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),設定逾時時間,逾時可以退出防止死鎖。
- 盡量使用java.util.concurrent(jdk 1.5以上)包的并發類代替手寫控制并發,比較常用的是ConcurrentHashMap、ConcurrentLinkedQueue、AtomicBoolean等等,實際應用中java.util.concurrent.atomic十分有用,簡單友善且效率比使用Lock更高 。
- 盡量降低鎖的使用粒度,盡量不要幾個功能用同一把鎖 。
- 盡量減少同步的代碼塊。
怎麼解除死鎖
- 隻要破壞死鎖産生的四個必要條件中的某個條件就能避免死鎖,一般不會采用破壞第一個條件來避免死鎖
源碼位址:https://github.com/jiangxlGit/steady/tree/master/steady