线程死锁
死锁是指两个或多个线程被阻塞,等待获得死锁中的其他线程所持有的锁。当多个线程同时需要相同的锁,但以不同的顺序获得它们时,就会发生死锁。
例如,如果线程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.