title: Avoiding deadlock using ReentrantLock
body: <p>I was doing some practice assignments and dabbling around with some dummy code for trying to develop a better understanding of the concepts of threads and locks. Following is a piece of code that (sometimes) goes into deadlock.</p>
  
  <p><em>A.java</em></p>
  
  <pre><code>public class A {
  
      private B b;
  
      public void setB(B b) {
          this.b = b;
      }
  
      public synchronized void foo(boolean callBar) {
          System.out.println("foo");
          if (callBar) {
              b.bar(false);
          }
      }
  }
  </code></pre>
  
  <p><em>B.java</em></p>
  
  <pre><code>public class B {
  
      private A a;
  
      public void setA(A a) {
          this.a = a;
      }
  
      public synchronized void bar(boolean callFoo) {
          System.out.println("bar");
          if (callFoo) {
              a.foo(false);
          }
      }
  }
  </code></pre>
  
  <p><em>Demo.java</em></p>
  
  <pre><code>public class Demo {
      public static void main(String[] args) {
      A a = new A();
      B b = new B();
  
      a.setB(b);
      b.setA(a);
  
      new Thread(() -&gt; {
          a.foo(true);
      }).start();
  
      new Thread(() -&gt; {
          b.bar(true);
      }).start();
      }
  }
  </code></pre>
  
  <p><strong>Solution</strong>: I used <code>Lock</code>s instead of <code>synchronized</code>.</p>
  
  <p><em>A.java</em></p>
  
  <pre><code>public class A {
  
      private final ReentrantLock lock = new ReentrantLock();
      private B b;
  
      public void setB(B b) {
          this.b = b;
      }
  
      public ReentrantLock lock() {
          return lock;
      }
  
      public boolean impendingExecute() {
          Boolean thisLock = false;
          Boolean otherLock = false;
          try {
              thisLock = lock.tryLock();
              otherLock = b.lock().tryLock();
          } finally {
              if (!(thisLock &amp;&amp; otherLock)) {
                  if (thisLock) {
                      lock.unlock();
                  }
                  if (otherLock) {
                      b.lock().unlock();
                  }
              }
          }
          return thisLock &amp;&amp; otherLock;
      }
  
      public void foo(boolean callBar) {
          System.out.println("foo");
          if (callBar &amp;&amp; impendingExecute()) {
              try {
                  b.bar(false);
              } finally {
                  lock.unlock();
                  b.lock().unlock();
              }
          }
      }
  }
  </code></pre>
  
  <p><em>B.java</em></p>
  
  <pre><code>public class B {
  
      private final ReentrantLock lock = new ReentrantLock();
      private A a;
  
      public void setA(A a) {
          this.a = a;
      }
  
      public ReentrantLock lock() {
          return lock;
      }
  
      public boolean impendingExecute() {
          Boolean thisLock = false;
          Boolean otherLock = false;
          try {
              thisLock = lock.tryLock();
              otherLock = a.lock().tryLock();
          } finally {
              if (!(thisLock &amp;&amp; otherLock)) {
                  if (thisLock) {
                      lock.unlock();
                  }
                  if (otherLock) {
                      a.lock().unlock();
                  }
              }
          }
          return thisLock &amp;&amp; otherLock;
      }
  
      public void bar(boolean callFoo) {
          System.out.println("bar");
          if (callFoo &amp;&amp; impendingExecute()) {
              try {
                  a.foo(false);
              } finally {
                  lock.unlock();
                  a.lock().unlock();
              }
          }
      }
  }
  </code></pre>
  
  <p>After making the above changes, the code doesn't lead to a deadlock. Is it the proper way to implement this (Basically, I want the <code>impendingExecute()</code> method to be reviewed.)? Also, (deviating a bit from the review) are there any real world scenarios I can encounter this?</p>
  
  <p><em>Note</em>: I had posted this question on Code Review but it seems reviewal of dummy code is off-topic.</p>