死鎖:當一個線程永遠地持有一個鎖,並且其他線程都嘗試獲得這個鎖時,那么它們將永遠被阻塞。比如,線程1已經持有了A鎖並想要獲得B鎖的同時,線程2持有B鎖並嘗試獲取A鎖,那么這兩個線程將永遠地等待下去。
我們來看一個死鎖的簡單例子:
1 public class DeadLockTest 2 { 3 private static Object A = new Object(), B = new Object(); 4 5 public static void main(String[] args) 6 { 7 new Thread(() -> { 8 System.out.println("線程1開始執行..."); 9 synchronized (A) 10 { 11 try 12 { 13 System.out.println("線程1拿到A鎖"); 14 //休眠兩秒讓線程2有時間拿到B鎖 15 Thread.sleep(2000); 16 } catch (Exception e) 17 { 18 e.printStackTrace(); 19 } 20 synchronized (B) 21 { 22 System.out.println("線程1拿到B鎖"); 23 } 24 } 25 }).start(); 26 27 new Thread(() -> { 28 System.out.println("線程2開始執行..."); 29 synchronized (B) 30 { 31 try 32 { 33 System.out.println("線程2拿到B鎖"); 34 //休眠兩秒讓線程1有時間拿到A鎖 35 Thread.sleep(2000); 36 } catch (Exception e) 37 { 38 e.printStackTrace(); 39 } 40 synchronized (A) 41 { 42 System.out.println("線程2拿到A鎖"); 43 } 44 } 45 }).start(); 46 47 } 48 }
運行結果:
從運行結果可看到,線程1拿到了A鎖,並嘗試去獲取B鎖,與此同時線程2拿到了B鎖並嘗試去獲取A鎖,此時線程1和線程2就陷入了無限的等待,形成死鎖。
那么要怎么預防死鎖呢?下面介紹幾個常見方法:
1、避免一個線程同時獲取多個鎖
2、避免一個線程在鎖內同時占用多個資源,盡量保證每個鎖只占用一個資源
3、嘗試使用定時鎖,使用lock.tryLock來代替使用內置鎖。
詳情可參考《Java並發編程實戰》