<!DOCTYPE qhelp PUBLIC
  "-//Semmle//qhelp//EN"
  "qhelp.dtd">
<qhelp>

<overview>
<p>
Acquiring two locks in an inconsistent order may result in deadlock if two threads simultaneously
attempt to acquire the locks, and each thread succeeds in acquiring one lock prior to being able
to acquire the other lock.
</p>
</overview>

<recommendation>
<p>
To guard against deadlock, use one of the following alternatives:
</p>

<ul>
<li>Define an ordering on locks, and ensure that clients respect that ordering when acquiring locks.</li>
<li>Simplify the code to only use a single lock, where possible.</li>
<li>Use <code>ReentrantLock</code>s and acquire locks using <code>tryLock()</code> instead of <code>lock()</code>.</li>
</ul>

</recommendation>

<example>
<p>
In the following example, one method acquires <code>primaryLock</code> followed by <code>savingsLock</code>, and
another method acquires these locks in reverse order. This may result in deadlock if the two methods are invoked by
two threads simultaneously, and each thread acquires one of the two locks prior to being able to acquire the other one.
</p>

<sample src="LockOrderInconsistency.java" />

<p>
One way to address the issue in the above example is to reverse the lock order in <code>transferToPrimary</code>
to match the lock order in <code>transferToSecondary</code>.
</p>

</example>

<references>

<li>The CERT Oracle Secure Coding Standard for Java:
  <a href="https://www.securecoding.cert.org/confluence/display/java/LCK07-J.+Avoid+deadlock+by+requesting+and+releasing+locks+in+the+same+order">LCK07-J. Avoid deadlock by requesting and releasing locks in the same order</a>.</li>
<li>
  Java Language Specification:
  <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.1">Synchronization</a>.</li>
<li>
  Java API Documentation:
  <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html">ReentrantLock</a>.</li>



<!--  LocalWords:  CWE
 -->

</references>

</qhelp>
