ReentrantReadWriteLock Class in Java
Last Updated :
26 May, 2022
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:
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
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReentrantReadWriteLockExample {
private static final ReentrantReadWriteLock lock
= new ReentrantReadWriteLock( true );
private static String message = "a" ;
public static void main(String[] args)
throws InterruptedException
{
Thread t1 = new Thread( new Read());
Thread t2 = new Thread( new WriteA());
Thread t3 = new Thread( new WriteB());
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
static class Read implements Runnable {
public void run()
{
for ( int i = 0 ; i <= 10 ; i++) {
if (lock.isWriteLocked()) {
System.out.println(
"I'll take the lock from Write" );
}
lock.readLock().lock();
System.out.println(
"ReadThread "
+ Thread.currentThread().getId()
+ "Message is " + message);
lock.readLock().unlock();
}
}
}
static class WriteA implements Runnable {
public void run()
{
for ( int i = 0 ; i <= 10 ; i++) {
try {
lock.writeLock().lock();
message = message.concat( "a" );
}
finally {
lock.writeLock().unlock();
}
}
}
}
static class WriteB implements Runnable {
public void run()
{
for ( int i = 0 ; i <= 10 ; i++) {
try {
lock.writeLock().lock();
message = message.concat( "b" );
}
finally {
lock.writeLock().unlock();
}
}
}
}
}
|
Output
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
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...