import java.util.*; public class TreeNode { String name = null; TreeNode parent = null; List children = new ArrayList<>(); public TreeNode(String name) { this.name = name; } public synchronized void addChild(TreeNode child){ if(!this.children.contains(child)) { this.children.add(child); System.out.println("Hi! Locked parent and attemping to lock child."); child.setParentOnly(this); System.out.println("Hi! Locked child as well."); } } public synchronized void addChildOnly(TreeNode child){ if(!this.children.contains(child)){ this.children.add(child); } } public synchronized void setParent(TreeNode parent){ this.parent = parent; System.out.println("Hi! Locked child and attemping to lock parent."); parent.addChildOnly(this); System.out.println("Hi! Locked parent as well."); } public synchronized void setParentOnly(TreeNode parent){ this.parent = parent; } public static void main(String args[]) { final TreeNode child = new TreeNode("child"); final TreeNode parent = new TreeNode("parent"); Thread a = new Thread(new Runnable() { public void run() { child.setParent(parent); } }); a.start(); Thread b = new Thread(new Runnable() { public void run() { parent.addChild(child); } }); b.start(); } }