Card 06/ 09

ComparisonDifficulty: Advanced1 min

synchronized vs ReentrantLock

The keyword releases itself; the class can time out, be interrupted and be released elsewhere.

ReentrantLock is a class that does what the synchronized keyword does, through method calls, and adds several things the keyword cannot express. Both are reentrant (a thread may take a lock it already holds) and both give the same exclusion and visibility, meaning a thread that takes the lock sees every write made under it; the table compares what else each can do, and the rule after it says which to use.

The two locking mechanisms, on what each can express
Compared onsynchronizedReentrantLock
Released automaticallyYes, on every exit from the blockNo: needs a finally
Give up after a timeoutNotryLock(5, SECONDS)
Give up immediately if heldNotryLock()
Interruptible while waitingNolockInterruptibly()
Acquire in one method, release in anotherNoYes
Fairness, first come first servedNoOptional, at a cost
java
private final ReentrantLock lock = new ReentrantLock();

void withdraw(long amount) {
    lock.lock();
    try {
        if (amount <= pence) { pence -= amount; }
    } finally {
        lock.unlock();
    }
}

The finally is not optional and not a style choice. Without it, an exception inside the block leaves the lock held forever and every other thread waits on it for the life of the process.

The decision rule. Use synchronized by default: it cannot be left unreleased, and it is shorter. Reach for ReentrantLock when you need one of the rows the keyword cannot do, and most often the one you need is the timeout on waiting.