我正在通过a Jakob Jenkov's concurrency tutorial,不理解在这段代码中如何发生死锁:

  public class TreeNode {
  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;
  }
}


作者的解释说:


  第一个线程1调用parent.addChild(child)。由于addChild()是
  同步线程1有效锁定父对象以进行访问
  从其他方面。
  
  然后线程2调用child.setParent(parent)。由于setParent()是
  同步线程2有效地锁定子对象以获取权限
  从其他线程。


由于所有4种方法都是“同步的”,因此所有这些方法都由“此”对象保护,因此恕我直言,第二个线程将不允许获取锁。还是我错了?

最佳答案

该示例指出


  这是一个调用同步方法的TreeNode类的示例
  在不同的情况下:


因此,两个进入synchronized方法的线程都将在不同的对象上同步,但是会导致死锁,因为这两个线程都锁定了自己的对象(父,子),然后尝试锁定“相反的”对象(子,父)。

该示例显示了以相同顺序锁定事物的重要性。

10-07 19:31
查看更多