ReentrantLock
An explicit lock — a flexible replacement for `synchronized`.
Available since: Java 1.5
Syntax
public class ReentrantLock implements LockExamples
A mandatory unlock() in finally:
class Account {
private final ReentrantLock lock = new ReentrantLock();
private int balance = 100;
boolean withdraw(int amount) {
lock.lock();
try {
if (balance < amount) return false;
balance -= amount;
return true;
} finally {
lock.unlock();
}
}
int balance() { return balance; }
}
void main() throws InterruptedException {
var acc = new Account();
var ok = new AtomicInteger();
Runnable task = () -> { for (int i = 0; i < 10; i++) if (acc.withdraw(10)) ok.incrementAndGet(); };
Thread a = new Thread(task), b = new Thread(task);
a.start(); b.start();
a.join(); b.join();
IO.println(ok.get() + " withdrawals, balance " + acc.balance());
}Output:
10 withdrawals, balance 0Notes
Always call unlock() in finally, otherwise an exception leaves the lock held forever. Unlike synchronized, it can wait with a timeout (tryLock(1, TimeUnit.SECONDS)), be interrupted and work in fair mode. If you do not need these features, synchronized is simpler.
See also
- synchronized — Lets only one thread at a time run a block of code.
- AtomicInteger — An integer that can be changed safely from several threads without locks.
In the tutorial
- Synchronization — Race conditions in Java and how to avoid them — synchronized methods and blocks, atomic classes like AtomicInteger, ReentrantLock and a shared lock object.