w3resource

Java Program: Concurrent Read-Write Access with ReadWriteLock

Java Multithreading: Exercise-7 with Solution

A ReadWriteLock maintains a pair of associated locks, one for read-only operations and one for writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

All ReadWriteLock implementations must guarantee that the memory synchronization effects of writeLock operations (as specified in the Lock interface) also hold with respect to the associated readLock. That is, a thread successfully acquiring the read lock will see all updates made upon previous release of the write lock.

A read-write lock allows for a greater level of concurrency in accessing shared data than that permitted by a mutual exclusion lock. It exploits the fact that while only a single thread at a time (a writer thread) can modify the shared data, in many cases any number of threads can concurrently read the data (hence reader threads). In theory, the increase in concurrency permitted by the use of a read-write lock will lead to performance improvements over the use of a mutual exclusion lock. In practice this increase in concurrency will only be fully realized on a multi-processor, and then only if the access patterns for the shared data are suitable.

Write a Java program to illustrate the usage of the ReadWriteLock interface for concurrent read-write access to a shared resource.

Sample Solution:

Java Code:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockExercise {
  private static final int NUM_READERS = 3;
  private static final int NUM_WRITERS = 2;

  public static void main(String[] args) {
    ReadWriteLock lock = new ReentrantReadWriteLock();
    SharedResource sharedResource = new SharedResource();

    // Create and start the reader threads
    for (int i = 0; i < NUM_READERS; i++) {
      Thread readerThread = new Thread(new Reader(lock, sharedResource));
      readerThread.start();
    }

    // Create and start the writer threads
    for (int i = 0; i < NUM_WRITERS; i++) {
      Thread writerThread = new Thread(new Writer(lock, sharedResource));
      writerThread.start();
    }
  }

  static class Reader implements Runnable {
    private ReadWriteLock lock;
    private SharedResource sharedResource;

    public Reader(ReadWriteLock lock, SharedResource sharedResource) {
      this.lock = lock;
      this.sharedResource = sharedResource;
    }

    public void run() {
      while (true) {
        lock.readLock().lock();

        // Read from the shared resource
        System.out.println("Reader " + Thread.currentThread().getName() + " reads: " + sharedResource.read());

        lock.readLock().unlock();

        // Delay between consecutive reads
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }

  static class Writer implements Runnable {
    private ReadWriteLock lock;
    private SharedResource sharedResource;
    private int counter = 0;

    public Writer(ReadWriteLock lock, SharedResource sharedResource) {
      this.lock = lock;
      this.sharedResource = sharedResource;
    }

    public void run() {
      while (true) {
        lock.writeLock().lock();

        // Write to the shared resource
        sharedResource.write("Writer " + Thread.currentThread().getName() + " writes: " + counter++);

        lock.writeLock().unlock();

        // Delay between consecutive writes
        try {
          Thread.sleep(2000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }

  static class SharedResource {
    private String data;

    public String read() {
      return data;
    }

    public void write(String data) {
      this.data = data;
    }
  }
}

Sample Output:

Reader Thread-2 reads: null
Reader Thread-0 reads: null
Reader Thread-1 reads: null
Reader Thread-2 reads: Writer Thread-4 writes: 0
Reader Thread-0 reads: Writer Thread-4 writes: 0
Reader Thread-1 reads: Writer Thread-4 writes: 0
Reader Thread-2 reads: Writer Thread-4 writes: 1
Reader Thread-0 reads: Writer Thread-4 writes: 1
Reader Thread-1 reads: Writer Thread-4 writes: 1
Reader Thread-2 reads: Writer Thread-4 writes: 1
Reader Thread-1 reads: Writer Thread-4 writes: 1
Reader Thread-0 reads: Writer Thread-4 writes: 1
Reader Thread-1 reads: Writer Thread-4 writes: 2

Explanation:

In the above exercise -

  • The "ReadWriteLockExample" class represents the main program. It creates an instance of the "ReentrantReadWriteLock" class, which implements the ReadWriteLock interface, and an instance of the SharedResource class.
  • The "Reader" class implements the Runnable interface and represents a reader thread. Each reader thread acquires the read lock using the readLock() method, reads from the shared resource, and then releases the read lock using the unlock() method. Readers can read from the shared resource concurrently without blocking each other.
  • The "Writer" class implements the Runnable interface and represents a writer thread. Each writer thread acquires the write lock using the writeLock() method, writes to the shared resource, and then releases the write lock using the unlock() method. Only one writer can write to the shared resource at a time, and writers block readers and other writers.
  • The "SharedResource" class represents shared resources. In this example, it has a read() method to read from the shared resource and a write() method to write to the shared resource.
  • In the main() method, we create and start multiple reader threads and writer threads. Readers can read concurrently from the shared resource, and writers can write one at a time while blocking readers and other writers.

Flowchart:

Flowchart: Java Program: Concurrent Read-Write Access with ReadWriteLock.
Flowchart: Java Program: Concurrent Read-Write Access with ReadWriteLock.
Flowchart: Java Program: Concurrent Read-Write Access with ReadWriteLock.

Java Code Editor:

Improve this sample solution and post your code through Disqus

Previous: Thread Synchronization with CountDownLatch.
Next: Concurrent Map Access with ConcurrentHashMap.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.