ReadWriteLock has two locks, one for read and one for write. Request for read lock from multiple threads can be acquired if there is no write request. If there is a write request, no other thread will be able to acquire read or write lock on that resource.
ReentrantReadWriteLock example:
It is an implementation of ReadWriteLock interface.
It has two kinds of locks i.e. ReaderLock and WriterLock.
Let’s understand it with the help of an example:
We will have three runnable interfaces. Reader, WriterEven and WriterOdd.
Reader: It will read number variable.
WriterEven: It will write even digit to the number.
WriterOdd: It will write odd digit to the number.
We are going to use ReentrantReadWriteLock with fairness as true.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
package org.arpit.java2blog;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReentrantReadWriteLockExampleMain {
private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
private static String number = "0";
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(new Reader(),"Read 1");
Thread t2 = new Thread(new Reader(),"Read 2");
Thread t3 = new Thread(new WriterOdd(),"Write odd");
Thread t4 = new Thread(new WriterEven(),"Write even");
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
}
static class Reader implements Runnable {
public void run() {
for(int i = 0; i<= 10; i ++) {
lock.readLock().lock();
System.out.println(Thread.currentThread().getName() + " ---> Number is " + number );
lock.readLock().unlock();
}
}
}
static class WriterOdd implements Runnable {
public void run() {
for(int i = 1; i<= 7; i+=2) {
try {
lock.writeLock().lock();
System.out.println("Writer odd is writing");
number = number.concat(" "+i);
} finally {
lock.writeLock().unlock();
}
}
}
}
static class WriterEven implements Runnable {
public void run() {
for(int i = 2; i<= 8; i +=2) {
try {
lock.writeLock().lock();
System.out.println("Writer Even is writing");
number = number.concat(" "+i);
} finally {
lock.writeLock().unlock();
}
}
}
}
}
|
When you run program, you will get below output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
Read 2 ---> Number is 0
Read 1 ---> Number is 0
Writer odd is writing
Writer Even is writing
Read 2 ---> Number is 0 1 2
Read 1 ---> Number is 0 1 2
Writer odd is writing
Writer Even is writing
Read 2 ---> Number is 0 1 2 3 4
Read 1 ---> Number is 0 1 2 3 4
Writer odd is writing
Writer Even is writing
Read 2 ---> Number is 0 1 2 3 4 5 6
Read 1 ---> Number is 0 1 2 3 4 5 6
Writer odd is writing
Writer Even is writing
Read 2 ---> Number is 0 1 2 3 4 5 6 7 8
Read 2 ---> Number is 0 1 2 3 4 5 6 7 8
Read 1 ---> Number is 0 1 2 3 4 5 6 7 8
Read 2 ---> Number is 0 1 2 3 4 5 6 7 8
Read 1 ---> Number is 0 1 2 3 4 5 6 7 8
Read 2 ---> Number is 0 1 2 3 4 5 6 7 8
Read 2 ---> Number is 0 1 2 3 4 5 6 7 8
Read 1 ---> Number is 0 1 2 3 4 5 6 7 8
Read 2 ---> Number is 0 1 2 3 4 5 6 7 8
Read 1 ---> Number is 0 1 2 3 4 5 6 7 8
Read 2 ---> Number is 0 1 2 3 4 5 6 7 8
Read 1 ---> Number is 0 1 2 3 4 5 6 7 8
Read 1 ---> Number is 0 1 2 3 4 5 6 7 8
Read 1 ---> Number is 0 1 2 3 4 5 6 7 8
|
As you can see, Reader threads are blocked when writer threads have acquired writeLock and also if writerEven has acquire writeLock then writerOdd won’t able to acquire writerLock until writerEven releases it or vice versa.
lock.readLock().lock() : It is used to request for readLock.
lock.readLock().unlock() : It is used to release readLock.
lock.writeLock().lock() : It is used to acquire writeLock.
lock.writeLock().unlock() : It is used to release writeLock.