ReadWriteLock Interface in Java
Locks are a fundamental feature in a multithreaded environment, allowing multiple threads to work on the same resources without resulting in any bugs and race conditions. In Java, multiple versions of locks exist, and the ReadWriteLock is one of them.
Locks manage the access to the resources in multithreaded programming. Two or more threads trying to access the same resources simultaneously can result in unexpected behaviour. Thus, a lock here ensures that only a limited number of threads can access the same file or resources simultaneously.
Note that any unexpected behaviour only occurs when two or more threads are writing on the same file or resources and not when they are reading from that resource. The ReadWriteLock, in Java, takes advantage of this feature that different threads can read from the same resource simultaneously, but only one thread can perform a write operation on the resource.
What is ReadWriteLock in Java?
The ReadWriteLock in Java is an interface that uses the mechanism of read-write lock. Using ReadWriteLock, the programmers can gain better performance and efficiency than the mutual exclusion lock as the mutual exclusion lock allows access to only one thread at a time.
Some important points about the ReadWriteLock interface in Java are mentioned below.
- The ReadWriteLock preserves a pair of linked locks. One is for the Read-only operations, and the other is for writing.
- Multiple threads can utilise the read lock until there is no write thread.
- The write lock is exclusive.
- The ReadWriteLock interface is part of the java.util.concurrent.locks package.
- The ReadWriteLock performs better than other locks in the application when there are more read operations than write operations.
Rules of the Read and Write Lock
Read Lock: When no thread has locked the lock for writing, in that scenario, multiple different thread can lock the lock to read from the resource simultaneously. In simpler terms, different threads can read from the resource until there is no thread to modify to write in the resource.
Write Lock: When there is no thread lock for writing or reading, in that scenario, only one thread can lock the lock for writing on the resource. The other thread needs to wait until the write lock is released. In simpler terms, at a moment, only a single thread can write on the resource, and the other threads must wait until that write lock is released.
Class Methods
The methods that can be used with the ReadWriteLock interface are explained in the table below.
Sr.No | Method | Detail |
readLock() | It returns the lock that is used for reading. | |
writeLock() | It returns the lock that is used for writing. |
Implementation
Now, Go through the example below where we have implemented the ReadWriteLock in Java.
FileName: ReadWriteLockExample.java
// Java Program to implement ReadWriteLock interface
// Import required libraries and packages
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockExample
{
private static final ReadWriteLock lock = new ReentrantReadWriteLock();
private static int counter = 0;
//Method that increments the counter variable
static void increment() {
lock.writeLock().lock();
try {
counter++;
} finally {
lock.writeLock().unlock();
}
}
//Method that returns the value of counter variable
static int getCounter() {
lock.readLock().lock();
try {
return counter;
} finally {
lock.readLock().unlock();
}
}
// Main Method
public static void main(String[] arg)
{
ExecutorService executorService = null;
try {
// Creates a Thread pool of size 4
executorService = Executors.newFixedThreadPool(4);
// Performs write operation
Runnable operation1 = () -> {
System.out.println(Thread.currentThread().getName() +
" Performing Write operation on Counter Variable");
for (int i = 0; i < 1000; i++) {
ReadWriteLockExample.increment();
}
};
// Performs Read operation
Runnable operation2 = () -> {
System.out.println(Thread.currentThread().getName() +
" Performing Read operation on Counter Variable");
int count = ReadWriteLockExample.getCounter();
System.out.println("The Final value of the Counter is: "+count);
};
// Performs Read operation
Runnable operation3 = () -> {
System.out.println(Thread.currentThread().getName() +
" Performing Read operation on Counter Variable");
int count = ReadWriteLockExample.getCounter();
System.out.println("The Final value of the Counter is: "+count);
};
// Performs Read operation
Runnable operation4 = () -> {
System.out.println(Thread.currentThread().getName() +
" Performing Read operation on Counter Variable");
int count = ReadWriteLockExample.getCounter();
System.out.println("The Final value of the Counter is: "+count);
};
// Submit the task or operation for Execution
executorService.submit(operation1);
executorService.awaitTermination(4, TimeUnit.SECONDS);
executorService.submit(operation2);
executorService.submit(operation3);
executorService.submit(operation4);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (executorService != null) {
executorService.shutdown();
}
}
}
}
Output:
pool-1-thread-1 Performing Write operation on Counter Variable
pool-1-thread-2 Performing Read operation on Counter Variable
pool-1-thread-3 Performing Read operation on Counter Variable
pool-1-thread-4 Performing Read operation on Counter Variable
The Final value of the Counter is: 1000
The Final value of the Counter is: 1000
The Final value of the Counter is: 1000