Skip to content
Dev Dump

πŸ”’ Custom Reader-Writer Lock in Java

A Reader-Writer Lock allows:

  • Multiple threads to read a resource simultaneously
  • But only one thread to write, and writers must have exclusive access

This solution implements: βœ… Thread-safe access
βœ… Prevention of writer starvation
βœ… Multiple readers, one writer at a time

  1. Multiple Readers: Multiple threads can read simultaneously when no writer is active
  2. Exclusive Writer: Only one writer can access the resource at a time
  3. Writer Priority: Writers should not starve due to continuous reader access
  4. Thread Safety: Must handle concurrent access from multiple reader and writer threads
  5. No Deadlocks: Solution must not deadlock under any circumstances
  6. Fair Access: Both readers and writers should get reasonable access to the resource

Input:

  • Multiple reader threads requesting read access
  • Multiple writer threads requesting write access
  • Shared resource that needs protection

Output:

  • Controlled access to the shared resource
  • Multiple concurrent readers when safe
  • Exclusive writer access when needed
  • Proper synchronization without deadlocks

The key insight is that we need to track three pieces of state: current readers, current writers, and pending write requests. Readers can proceed when there are no active writers or pending write requests. Writers can proceed when there are no active readers or writers. The write request counter prevents writer starvation by giving priority to writers over new readers.

  1. Design the state variables: Track readers, writers, and write requests
  2. Implement read lock acquisition: Allow multiple readers when no writers active
  3. Implement write lock acquisition: Ensure exclusive access for writers
  4. Handle write requests: Track pending writes to prevent reader starvation
  5. Implement proper release: Decrement counters and notify waiting threads
  6. Add safety checks: Ensure proper state transitions
  1. Writer starvation: Handle when readers continuously acquire locks
  2. Reader starvation: Handle when writers continuously acquire locks
  3. Concurrent releases: Handle multiple threads releasing locks simultaneously
  4. Thread interruption: Handle InterruptedException properly
  5. Spurious wakeups: Use while loops to check conditions after waking up
  6. State consistency: Ensure counters never go negative
/**
* A reader-writer lock that allows multiple readers to access a resource
* simultaneously, but only one writer at a time.
*/
public class ReaderWriterLock {
private int readers = 0; // Current number of active readers
private int writers = 0; // Current number of active writers
private int writeRequests = 0; // Number of threads waiting to write
public synchronized void acquireReadLock() throws InterruptedException {
// Wait until there are no active writers or pending write requests
while (writers > 0 || writeRequests > 0) {
wait();
}
readers++; // Increment reader count
}
public synchronized void releaseReadLock() {
readers--; // Decrement reader count
if (readers == 0) {
notifyAll(); // Notify waiting writers when no readers remain
}
}
public synchronized void acquireWriteLock() throws InterruptedException {
writeRequests++; // Increment write request count to prevent new readers
// Wait until there are no active readers or writers
while (readers > 0 || writers > 0) {
wait();
}
writeRequests--; // Decrement write request count
writers++; // Increment writer count
}
public synchronized void releaseWriteLock() {
writers--; // Decrement writer count
notifyAll(); // Notify all waiting threads
}
public synchronized int getReaderCount() {
return readers; // Return current number of active readers
}
public synchronized boolean isWriteLocked() {
return writers > 0; // Check if any writer is currently active
}
public synchronized int getWriteRequests() {
return writeRequests; // Return number of pending write requests
}
}

Scenario: 2 readers and 1 writer competing for access

Initial State:

  • readers = 0, writers = 0, writeRequests = 0

Step 1: Reader 1 wants to read

  • Check: writers > 0 || writeRequests > 0 β†’ false (0 > 0 || 0 > 0)
  • Increment readers to 1
  • Reader 1 can proceed

Step 2: Reader 2 wants to read

  • Check: writers > 0 || writeRequests > 0 β†’ false (0 > 0 || 0 > 0)
  • Increment readers to 2
  • Reader 2 can proceed

Step 3: Writer wants to write

  • Increment writeRequests to 1
  • Check: readers > 0 || writers > 0 β†’ true (2 > 0 || 0 > 0)
  • Writer waits

Step 4: Reader 1 finishes reading

  • Decrement readers to 1
  • readers != 0, so no notification
  • Writer still waits

Step 5: Reader 2 finishes reading

  • Decrement readers to 0
  • readers == 0, so notifyAll()
  • Writer wakes up and checks: readers > 0 || writers > 0 β†’ false (0 > 0 || 0 > 0)
  • Decrement writeRequests to 0
  • Increment writers to 1
  • Writer can proceed

Result: Multiple readers can read simultaneously, writer gets exclusive access when no readers remain.

Time Complexity:

  • Read lock acquisition: O(1) - constant time to check conditions and update state
  • Write lock acquisition: O(1) - constant time to check conditions and update state
  • Lock release: O(1) - constant time to update state and notify threads
  • Waiting time: O(1) - constant time to block/unblock threads

Space Complexity:

  • State variables: O(1) - constant space for counters
  • Thread management: O(1) - constant space regardless of number of threads
  • Synchronization overhead: O(1) - constant space for intrinsic locks

ReaderWriterLock lock = new ReaderWriterLock();
// Reader thread
new Thread(() -> {
try {
lock.acquireReadLock();
System.out.println("πŸ” Reading data...");
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.releaseReadLock();
}
}).start();
// Writer thread
new Thread(() -> {
try {
lock.acquireWriteLock();
System.out.println("✍️ Writing data...");
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
lock.releaseWriteLock();
}
}).start();

FeatureDescription
πŸ‘₯ Multiple Concurrent ReadersReaders can access simultaneously if no writer is active
πŸ§β€β™‚οΈ Exclusive Writer AccessOnly one writer allowed, no readers during writing
⏳ Writer PriorityPrevents writer starvation by delaying new readers
πŸ” Thread SafeAll methods are synchronized
πŸ›‘οΈ Deadlock PreventionProper wait/notify management avoids deadlocks

This ReaderWriterLock class:

  • Balances concurrency and data integrity
  • Enables fine-grained access control
  • Prioritizes fairness and avoids starvation