多執行緒死鎖經典案例,必定會發生死鎖
Java執行緒死鎖是一個經典的多執行緒問題,因為不同的執行緒都在等待根本不可能被釋放的鎖,從而導致所有的任務都無法繼續完成。換言之只要互相等待對方釋放鎖就有可能出現死鎖。下面將用一個簡單的例子加以說明,如有問題,請多多指教。
某日AB兩位壯士各獲一張一模一樣的藏寶圖,他們相距甚遠,互不認識。兩位壯士不僅武藝雙全,還富有謀略,細讀藏寶圖,壯士得知寶藏就在某處,但是需要兩把鑰匙才能開啟,而這兩把鑰匙分別存在了某處,恰巧壯士A離鑰匙1更近,壯士B離鑰匙2更近,於是他們採用就近原則開啟尋寶之路。A先找到了鑰匙1,為了安全起見,A把鑰匙收入囊中,這時B也找到了鑰匙2,為了安全起見,B也把鑰匙收入囊中。他們各自開始尋找第二把鑰匙,但是到達他們原定的目的地之後並沒有找到鑰匙(其實都被對方據為己有了),但是心有不甘,心想這絕不能半途而廢,他們就這樣一直在苦苦等待尋找著......
上面就是多執行緒死鎖的經典案例,兩個人可看作是兩個不同的執行緒,A獲得了一把鎖a想嘗試獲取另外一把鎖b,B獲取了一把鎖b想嘗試獲取另外一把鎖a,他們互相持有對方想要的鎖,在沒有獲取到對方的鎖之前,是不會將自己的鎖給放棄的,這樣雙方永遠也無法集齊兩把鎖,於是發生了死鎖。
下面用程式碼來實現上面的場景:
public class DeathlyLockService { //鑰匙一 private Object lock1 = new Object(); //鑰匙二 private Object lock2 = new Object(); //開啟寶藏之方法,線路不同,先後獲取到的鑰匙也不同 public void openTreasure() throws Exception{ //線路一 if(Thread.currentThread().getName().equals("大AAA")){ //先獲取的是鑰匙一 synchronized (lock1) { System.out.println("執行緒"+Thread.currentThread().getName()+"拿到了lock1"); //成功獲取到一枚鑰匙,繼續尋找 Thread.sleep(2000); //嘗試獲取第二把鑰匙 synchronized(lock2){ //成功獲取到第二把鑰匙 System.out.println("執行緒"+Thread.currentThread().getName()+"拿到了lock2"); Thread.sleep(2000); //開啟了寶藏 System.out.println("執行緒"+Thread.currentThread().getName()+"集齊了兩把鑰匙開寶藏成功"); } } } //線路二 if(Thread.currentThread().getName().equals("小BBB")){ //先獲取鑰匙二 synchronized (lock2) { System.out.println("執行緒"+Thread.currentThread().getName()+"拿到了lock2"); //成功獲取到一枚鑰匙,繼續尋找 Thread.sleep(2000); //嘗試獲取第二把鑰匙 synchronized(lock1){ //成功獲取到第二把鑰匙 System.out.println("執行緒"+Thread.currentThread().getName()+"拿到了lock1"); Thread.sleep(2000); //開啟了寶藏 System.out.println("執行緒"+Thread.currentThread().getName()+"集齊了兩把鑰匙開寶藏成功"); } } } } }
//自定義執行緒 public class MyThread extends Thread{ private DeathlyLockService deathlyLockService; public MyThread(DeathlyLockService deathlyLockService){ this.deathlyLockService=deathlyLockService; } @Override public void run(){ try { System.out.println("執行緒"+Thread.currentThread().getName()+"開始執行"); deathlyLockService.openTreasure(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
main方法測試:
//互相持有對方的鎖,比如A物件進行操作時,需要B物件釋放鎖,此時B物件正在操作,需要A物件釋放鎖
DeathlyLockService s = new DeathlyLockService();
Thread a = new MyThread(s);
a.setName("大AAA");
a.start();
Thread b = new MyThread(s);
b.setName("小BBB");
b.start();
列印結果永遠卡在:
執行緒小BBB開始執行
執行緒大AAA開始執行
執行緒小BBB拿到了lock2
執行緒大AAA拿到了lock1
。。。。。。
結論:因為發生了死鎖,他們倆永遠無法獲取寶藏。知道了怎樣會發生死鎖,就知道如何避免這種情況的發生,希望大家以後都能開心的尋寶。