線程死鎖
死鎖是指兩個或多個線程被阻塞,等待獲得死鎖中的其他線程所持有的鎖。當多個線程同時需要相同的鎖,但以不同的順序獲得它們時,就會發生死鎖。
例如,如果線程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.