Locks

ReentrantLock

java.util.concurrent.locks gives more control than synchronized.

FeaturesynchronizedReentrantLock
Releaseautomaticmanual: unlock() in finally
Try without waiting / with timeoutnotryLock(), tryLock(1, SECONDS)
Interruptible waitnolockInterruptibly()
Fairness (FIFO)nonew ReentrantLock(true)
Several wait conditionsone (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(); }
    }
}