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.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章