Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk6 min

Reader-Writer Lock in Java: Solving the Library Problem in LLD

A reader-writer lock lets library catalog reads overlap while keeping inventory changes exclusive. Learn the invariants, fairness tradeoffs, upgrade and downgrade rules, and when measurement supports using one in Java.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For the library problem in low-level design, protect shared catalog or inventory state so multiple operations can read it concurrently, while any operation that changes it runs alone. Java’s ReadWriteLock expresses that contract with a shared read lock and an exclusive write lock. It helps coordinate access; it does not, by itself, make an entire application correct or guarantee better performance.

What problem does a reader-writer lock solve?

Imagine a library catalog stored as a map from book IDs to book records. Many threads may look up a title or inspect availability at the same time. Adding, removing, or updating a record changes shared state and must not overlap with another read or write that relies on that state being stable.

A reader-writer lock provides two modes:

  • Read lock: multiple threads may hold it concurrently, provided no thread holds the write lock.
  • Write lock: one thread holds it exclusively; while it is held, no reader or other writer can hold the lock.

That is the safety contract, not a complete library design. You must still decide what the shared state is, protect every access to it consistently, and define application rules such as whether a book may be checked out when no copy is available. Oracle’s Java SE 8 ReadWriteLock documentation also specifies that a successful read-lock acquisition observes updates made before a prior write-lock release.

How should you model the library state and lock boundaries?

Start with one clearly identified mutable state object, such as a map keyed by book ID, and one lock that protects it. Keep each critical section limited to the complete period in which the operation reads or changes that state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Catalog lookups and inventory inspections acquire the read lock before accessing the map and release it only after the inspection is finished.
  • Adding, removing, or updating a book acquires the write lock for the mutation.
  • Every code path that touches the protected mutable state must use the same lock discipline. Protecting writes but leaving some reads unlocked defeats the coordination contract.
  • Do not return a mutable internal collection or record for callers to modify after the lock is released. Return a safe snapshot, an immutable value, or use another explicit synchronization strategy.

A simple implementation using ReentrantReadWriteLock can make the boundaries visible:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

final class LibraryCatalog {
    private final ReentrantReadWriteLock rwLock =
            new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private final Map<String, Book> books = new HashMap<>();

    Book find(String id) {
        readLock.lock();
        try {
            return books.get(id); // Book should be immutable or safely copied.
        } finally {
            readLock.unlock();
        }
    }

    void add(Book book) {
        writeLock.lock();
        try {
            books.put(book.id(), book);
        } finally {
            writeLock.unlock();
        }
    }

    void remove(String id) {
        writeLock.lock();
        try {
            books.remove(id);
        } finally {
            writeLock.unlock();
        }
    }
}

The example assumes a Book type with an id() accessor and, for safe return from find, immutable contents or a suitable copy. The lock protects the map; it does not automatically protect mutable objects stored inside it if callers can change those objects independently.

Which fairness policy should you choose?

ReentrantReadWriteLock is nonfair by default. Under continuous contention, the Java SE 18 class documentation warns that a nonfair lock may indefinitely postpone a reader or writer, although it will normally have higher throughput than fair mode. This is a starvation risk to consider when delays matter, not a prediction that every nonfair workload will starve.

Fair mode uses an approximate arrival-order policy, not a strict FIFO promise for every acquisition. A longest-waiting writer may be selected for the write lock; a group of readers that have waited longer than all waiting writers may be selected for the read lock. The untimed tryLock() methods do not honor the fairness setting.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose based on the service requirement: nonfair mode favors throughput in the usual case, while fair mode can reduce the risk of prolonged postponement under contention at a potential throughput cost. Fairness does not guarantee a maximum wait time.

How do lock upgrade and downgrade work?

The Java SE 18 ReentrantReadWriteLock reference documents reentrancy and an important asymmetry: a writer can acquire the read lock, but a reader cannot acquire the write lock while retaining the read lock. Attempting a read-to-write upgrade can wait indefinitely because the thread’s own read hold prevents the writer from getting exclusive access.

When a read discovers work that requires a write

Release the read lock, acquire the write lock, then check the condition again before mutating. Another thread may have changed the state during the interval between releasing the read lock and acquiring the write lock, so acting on the earlier observation could be incorrect.

readLock.lock();
try {
    if (needsUpdate()) {
        // Do not acquire writeLock while still holding readLock.
    }
} finally {
    readLock.unlock();
}

writeLock.lock();
try {
    if (needsUpdate()) { // Recheck while holding exclusive access.
        performUpdate();
    }
} finally {
    writeLock.unlock();
}

When a writer needs to continue reading

Downgrade by acquiring the read lock while still holding the write lock, then releasing the write lock. This avoids an unlocked gap between the write and subsequent read phases. The order matters: releasing the write lock first would allow another thread to change the state before the read phase begins.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Oracle’s Java SE 18 reference illustrates these patterns with a cache-validity example: it releases the read lock before acquiring the write lock, checks validity again, and downgrades by obtaining the read lock before releasing the write lock. Its collection example similarly uses the read lock for TreeMap retrieval and key enumeration, and the write lock for put and clear.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When is a read-write lock worthwhile?

A read-write lock is a workload-dependent optimization, not an automatic upgrade over a mutual-exclusion lock. It is a candidate when reads are frequent and sufficiently long to benefit from parallel execution, writes are less frequent, and there is meaningful contention on hardware able to run multiple threads concurrently.

Compare the actual workload along these dimensions:

  • Read-to-write ratio: frequent updates reduce the periods in which readers can run together.
  • Critical-section duration: very short reads may not repay the extra coordination overhead.
  • Contention and parallelism: simultaneous readers matter only when threads contend and the system can execute them usefully in parallel.
  • Delay requirements: consider whether reader or writer postponement is acceptable and which fairness policy fits.
  • Complexity risk: longer lock holds and complicated lock transitions increase the chance of bottlenecks or mistakes.

For a basic library design, begin with correct state ownership and simple lock boundaries. A single mutual-exclusion lock may be easier to reason about and can perform as well as or better than a read-write lock when writes are common or reads are brief. The Java SE 8 API documentation puts the performance question plainly: “Ultimately, only profiling and measurement will establish whether the use of a read-write lock is suitable for your application.” It provides no universal speedup figure; measure your own operations and contention before choosing on performance grounds.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How to explain the design in an LLD interview

  1. Name the shared state: for example, a book-ID-to-book map and any related mutable inventory counts.
  2. State the invariants: reads may overlap only in the absence of a writer; all mutations are exclusive; every access follows the same synchronization policy.
  3. Choose and justify the lock: use a read-write lock when concurrent reads are a credible workload benefit; otherwise prefer the simpler mutex until measurements justify more complexity.
  4. Address fairness and transitions: note the default nonfair policy, the possibility of postponement, the need to release-and-recheck for a write after reading, and the safe write-to-read downgrade order.
  5. Bound the claim: explain that the lock protects the critical shared state, not unrelated application behavior or mutable objects that escape the lock.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.