Берегите ноги господа:
package wayerr.testlock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
    private static final ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(() -> {
            try {
                recursion();
            } catch(java.lang.StackOverflowError e) {
                // it expected
            }
        });
        thread.start();
        thread.join();
        System.out.println("Lock is locked: " + lock.isLocked());
        if(lock.tryLock()) {
            try {
                System.out.println("OK");
            } finally {
                lock.unlock();
            }
        } else {
            System.out.println("FAIL");
        }
    }
    static final void recursion() {
        lock.lock();
        try {
            recursion();
        } finally {
            lock.unlock();
        }
    }
}
В _этом_ тесте всегда выдает:
Lock is locked: true
FAIL
Чсх, на продакшене искать причину крайне весело, особенно с учетом того что в реальном коде он проявляться будет не всегда. Если метод recursion - не пустой то вероятность что стек кончится внутри lock - уменьшается.
зы. с каждым таким фокусом все больше любишь старый добрый synchronized .
ps. это починили в 9-ке: http://bugs.java.com/view_bug.do?bug_id=8046936 хотя известно с 11 года







