1. 程式人生 > 程式設計 >Java併發程式設計預防死鎖過程詳解

Java併發程式設計預防死鎖過程詳解

這篇文章主要介紹了Java併發程式設計預防死鎖過程詳解,文中通過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

在java併發程式設計領域已經有技術大咖總結出了發生死鎖的條件,只有四個條件都發生時才會出現死鎖:

1.互斥,共享資源X和Y只能被一個執行緒佔用

2.佔有且等待,執行緒T1已經取得共享資源X,在等待共享資源Y的時候,不釋放共享資源X

3.不可搶佔,其他執行緒不能強行搶佔執行緒T1佔有的資源

4.迴圈等待,執行緒T1等待執行緒T2佔有的資源,執行緒T2等待執行緒T1佔有的資源,就是迴圈等待

只要能破壞其中一個,就可以成功避免死鎖的發生,因為對於共享資源我們要得就是互斥的效果,所以第一個條件是無法破壞的,所以可以從下面三個條件出手,具體實現方式:

1.對於“佔用且等待”這個條件,我們可以一次性申請所有的資源,這樣就不存在等待了

class Allocator{
    //通過破壞佔有且等待條件避免死鎖現象的發生
    private List<Object> als = new ArrayList<>();
    //一次申請所有的資源
    synchronized boolean apply(Object from,Object to){
      if (als.contains(from) || als.contains(to)){
        //只要存在一個賬戶被其他的業務鎖定則無法完成轉賬業務
        return false;
      }else {
        als.add(from);
        als.add(to);
      }
      return true;
    }
    //歸還資源
    synchronized void free(Object from,Object to){
      als.remove(from);
      als.remove(to);
    }
  }
  class Account {
    //actr應該為單例
    private Allocator actr;
    private int balance;
    //轉賬
    void transfer(Account target,int amt){
      //一次性申請轉出和轉入賬戶,直到成功
      while (!actr.apply(this,target));
      try{
        //鎖定轉出賬戶
        synchronized (this){
          //鎖定轉入賬戶
          synchronized (target){
            if (this.balance > amt){
              this.balance -= amt;
              target.balance += amt;
            }
          }
        }
      }finally {
        actr.free(this,target);
      }
    }
  }

2.對於“不可搶佔”這個條件,佔用部分資源的執行緒進一步申請其他資源時,如果申請不到,可以主動釋放它所佔有的資源,這樣不可搶佔這個條件就破壞掉了

 3.對於“迴圈等待”這個條件,可以靠按序申請資源來預防,所謂按序申請,是指資源是有線性順序的,申請的時候可以先申請資源序號小的,再申請資源序號大的,這樣線性化後自然就不存在迴圈了

class Accounts{
    private int id;
    private int balance;
    //轉賬
    void transfer(Accounts target,int amt){
      Accounts left = this;
      Accounts right = target;
      if (this.id > target.id){
        left = target;
        right = this;
      }
      //鎖定序號小的賬戶
      synchronized (left){
        //鎖定序號大的賬戶
        synchronized (right){
          if (this.balance > amt){
            this.balance -= amt;
            target.balance += amt;
          }
        }
      }
    }
  }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。