ReentrantReadWriteLock Class in Java
ReentrantReadWriteLock class of Java is an implementation of ReadWriteLock, that also supports ReentrantLock functionality.
The ReadWriteLock is a pair of associated locks, one for read-only operations and one for writing. Whereas, the ReentrantLock is a re-entrant mutual exclusion Lock with the same behavior as the implicit monitor lock accessed using synchronized methods and statements, but with some more extended capabilities.
ReadWriteLock in Java
Even in a multi-threading application, multiple reads can occur simultaneously for a shared resource. It is only when multiple writes happen simultaneously or intermix of read and write that there is a chance of writing the wrong value or reading the wrong value.
ReadWriteLock in Java uses the same idea in order to boost the performance by having separate pair of locks. 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.
Having a pair of 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).
A read-write lock will improve performance over the use of a mutual exclusion lock if the frequency of reads is more than writes, duration of the read operations is more than the duration of the writes. It also depends on the contention for the data – that is, the number of threads that will try to read or write the data at the same time.
Package explorer view
• java.lang.Object • java.util.concurrent.locks.ReentrantReadWriteLock
Syntax: Importing the class
public class ReentrantReadWriteLock extends Object implements ReadWriteLock, Serializable
Constructor Summary
- ReentrantReadWriteLock(): Creates a new ReentrantReadWriteLock with default (nonfair) ordering properties.
- ReentrantReadWriteLock(boolean fair): Creates a new ReentrantReadWriteLock with the given fairness policy.
Exception thrown:
- NullPointerException: if the lock is null
Implementation:
We are going to have created three Runnable implementations. They all use a ReentrantReadWriteLock lock variable. The lock is created using the ReentrantReadWriteLock(boolean fair) constructor, so it is given a fairness policy:
- Read gets the lock. It uses the readLock() API method of ReentrantReadWriteLock to get a ReadLock. Then, it acquires the read lock, using the lock() method of ReadLock. While having the lock, it reads the value of a String message variable. Then it attempts to release the lock, using the unlock() method of ReadLock.
- Both WriteA and WriteB also get the lock, using writeLock() method, that returns a WriteLock, and then using unlock() method of WriteLock. Since having the write lock, they both alter the value of the String message variable. Then, they release the write lock, using the unlock() method of WriteLock.
Example
Java
// Java Program to Illustrate ReentrantReadWriteLock Class // Importing ReentrantReadWriteLock // fro java.util package import java.util.concurrent.locks.ReentrantReadWriteLock; // Class 1 // Main class public class ReentrantReadWriteLockExample { private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock( true ); // Initially the string contains only 1 character private static String message = "a" ; // Main driver method public static void main(String[] args) throws InterruptedException { // Creating threads Thread t1 = new Thread( new Read()); Thread t2 = new Thread( new WriteA()); Thread t3 = new Thread( new WriteB()); // Starting threads with help of start() method t1.start(); t2.start(); t3.start(); t1.join(); t2.join(); t3.join(); } // Class 2 // Helper class implementing Runnable interface static class Read implements Runnable { // run() method for thread public void run() { for ( int i = 0 ; i <= 10 ; i++) { if (lock.isWriteLocked()) { System.out.println( "I'll take the lock from Write" ); } // operating lock() lock.readLock().lock(); System.out.println( "ReadThread " + Thread.currentThread().getId() + "Message is " + message); lock.readLock().unlock(); } } } // Class 3 // Helper class implementing Runnable interface static class WriteA implements Runnable { // run() method for thread public void run() { for ( int i = 0 ; i <= 10 ; i++) { // Try block to check fr exceptions try { lock.writeLock().lock(); message = message.concat( "a" ); } finally { lock.writeLock().unlock(); } } } } // Class 4 // Helper class implementing Runnable interface static class WriteB implements Runnable { // run() method for thread public void run() { for ( int i = 0 ; i <= 10 ; i++) { // Try block to check for exceptions try { lock.writeLock().lock(); message = message.concat( "b" ); } finally { lock.writeLock().unlock(); } } } } } |
ReadThread 11 ---> Message is a ReadThread 11 ---> Message is aba ReadThread 11 ---> Message is ababa ReadThread 11 ---> Message is abababa ReadThread 11 ---> Message is ababababa ReadThread 11 ---> Message is abababababa ReadThread 11 ---> Message is ababababababa ReadThread 11 ---> Message is abababababababa ReadThread 11 ---> Message is ababababababababa ReadThread 11 ---> Message is abababababababababa ReadThread 11 ---> Message is ababababababababababa
Contact Us