Java併發編程之死鎖

Java併發編程之死鎖

線程死鎖

死鎖是指兩個或多個線程被阻塞,等待獲得死鎖中的其他線程所持有的鎖。當多個線程同時需要相同的鎖,但以不同的順序獲得它們時,就會發生死鎖。
例如,如果線程1鎖定了A並試圖鎖定B,而線程2已經鎖定了B並試圖鎖定A,那麼就會出現死鎖。線程1永遠不會得到B,線程2永遠不會得到a。此外,它們都不會知道。它們將永遠阻塞各自的對象A和B。這種情況就是死鎖。

Thread1  lock A,wait B
Thread2  lock B,wait A

實例代碼:

TreeNode parent   = null;  
List     children = new ArrayList();

  public synchronized void addChild(TreeNode child){
    if(!this.children.contains(child)) {
      this.children.add(child);
      child.setParentOnly(this);
    }
  }
  
  public synchronized void addChildOnly(TreeNode child){
    if(!this.children.contains(child){
      this.children.add(child);
    }
  }
  
  public synchronized void setParent(TreeNode parent){
    this.parent = parent;
    parent.addChildOnly(this);
  }

  public synchronized void setParentOnly(TreeNode parent){
    this.parent = parent;
  } 

如果一個線程A在另一個父線程B調用child.setParent(parent)方法的同時調用parent.addChild(child)方法,則在相同的父實例和子實例上,可能會發生死鎖.
注意:如上所述,這兩個線程必須同時調用parent. addchild (child)和child. setparent (parent),並且在相同的兩個父實例和子實例上纔會發生死鎖。
線程確實需要同時獲取鎖。例如,如果線程1比線程2早一點,因此鎖定了a和B,那麼線程2在嘗試鎖定B時就已經被阻塞了,這樣就不會發生死鎖。由於線程調度通常是不可預測的,所以無法預測何時發生死鎖。

數據庫死鎖

可能發生死鎖的更復雜的情況是數據庫事務。一個數據庫事務可能包含許多SQL更新請求。當一個記錄在一個事務期間被更新時,該記錄將被鎖定以接受其他事務的更新,直到第一個事務完成爲止。因此,同一事務中的每個更新請求可能會鎖定數據庫中的一些記錄。
如果多個事務同時運行,需要更新相同的記錄,則有可能導致死鎖。
代碼描述:

Transaction 1, request 1, locks record 1 for update
Transaction 2, request 1, locks record 2 for update
Transaction 1, request 2, tries to lock record 2 for update.
Transaction 2, request 2, tries to lock record 1 for update.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章