ReentrantLock vs synchronized — what does ReentrantLock add? — Cracked Java
MidTheoryBig TechAmazonGoogle

ReentrantLock vs synchronized — what does ReentrantLock add?

ReentrantLock gives the same mutual exclusion and reentrancy as synchronized, but adds capabilities the keyword cannot offer: interruptible and timed acquisition, non-blocking tryLock, optional fairness, multiple Condition wait-sets, and the ability to lock and unlock across method boundaries.

What ReentrantLock adds

  • Timed / interruptible acquisitiontryLock(timeout, unit) and lockInterruptibly(). A thread blocked on synchronized cannot be interrupted; one blocked on lockInterruptibly() can.
  • Non-blocking attempttryLock() returns immediately with true/false, enabling back-off strategies that avoid deadlock.
  • Fairnessnew ReentrantLock(true) grants the lock in FIFO order. synchronized is always unfair.
  • Multiple conditionsnewCondition() lets you have separate "not full" and "not empty" wait-sets on one lock; a monitor has exactly one.
  • IntrospectionisLocked(), getHoldCount(), hasQueuedThreads().

The cost: you own the unlock

synchronized releases the monitor automatically on scope exit. An explicit lock does not — you must release it yourself, always in finally:

private final ReentrantLock lock = new ReentrantLock();

public void transfer(Account to, long amount) {
    lock.lock();                 // acquire (reentrant: nested lock() is fine)
    try {
        balance -= amount;
        to.deposit(amount);
    } finally {
        lock.unlock();           // MUST run even if the body throws
    }
}

Both are reentrant: the same thread may re-acquire the lock it already holds (getHoldCount() increments), and must unlock() the same number of times.

When to use which

Prefer synchronized by default — it is less error-prone (no leaked locks), reads cleanly, and the JVM optimizes it well (lock coarsening, biased locking history). Reach for ReentrantLock only when you need one of its extra features. Both provide identical happens-before/visibility guarantees, so there is no memory-model reason to switch.

Mark your status