Careeroza
Locks
ReentrantLock
java.util.concurrent.locks gives more control than synchronized.
| Feature | synchronized | ReentrantLock |
|---|---|---|
| Release | automatic | manual: unlock() in finally |
| Try without waiting / with timeout | no | tryLock(), tryLock(1, SECONDS) |
| Interruptible wait | no | lockInterruptibly() |
| Fairness (FIFO) | no | new ReentrantLock(true) |
| Several wait conditions | one (wait/notify) | many Condition objects |
tryLock Avoids Waiting Forever
Example
A wallet that refuses a second concurrent payment instead of blocking.
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class Main {
public static void main(String[] args) throws Exception {
Wallet wallet = new Wallet(500);
CountDownLatch insidePayment = new CountDownLatch(1);
CountDownLatch finish = new CountDownLatch(1);
Thread slowPayment = new Thread(() -> wallet.pay(200, insidePayment, finish));
slowPayment.start();
insidePayment.await(); // slow payment now holds the lock
System.out.println("Second payment accepted? " + wallet.tryPay(100));
finish.countDown();
slowPayment.join();
System.out.println("Third payment accepted? " + wallet.tryPay(100));
System.out.println("Balance: " + wallet.balance());
}
}
class Wallet {
private final ReentrantLock lock = new ReentrantLock();
private int balance;
Wallet(int balance) { this.balance = balance; }
void pay(int amount, CountDownLatch inside, CountDownLatch finish) {
lock.lock();
try {
inside.countDown();
finish.await();
balance -= amount;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.unlock(); // always in finally
}
}
boolean tryPay(int amount) {
if (!lock.tryLock()) return false;
try { balance -= amount; return true; }
finally { lock.unlock(); }
}
int balance() { lock.lock(); try { return balance; } finally { lock.unlock(); } }
}Output
Second payment accepted? false Third payment accepted? true Balance: 200
ReadWriteLock and StampedLock
ReentrantReadWriteLock allows many readers at once but only one writer — good for caches that are read far more than written. StampedLock (Java 8) adds optimistic reads for even less contention.
class PriceCache {
private final Map<String, Integer> prices = new HashMap<>();
private final ReadWriteLock rw = new ReentrantReadWriteLock();
Integer get(String sku) {
rw.readLock().lock();
try { return prices.get(sku); } finally { rw.readLock().unlock(); }
}
void put(String sku, int price) {
rw.writeLock().lock();
try { prices.put(sku, price); } finally { rw.writeLock().unlock(); }
}
}