Appearance
ReadWriteLock
Earlier, we discussed how ReentrantLock
ensures that only one thread can execute critical section code at a time:
java
public class Counter {
private final Lock lock = new ReentrantLock();
private int[] counts = new int[10];
public void inc(int index) {
lock.lock();
try {
counts[index] += 1;
} finally {
lock.unlock();
}
}
public int[] get() {
lock.lock();
try {
return Arrays.copyOf(counts, counts.length);
} finally {
lock.unlock();
}
}
}
However, sometimes this kind of protection is excessive. For instance, while it is necessary to acquire the lock for modifying data via the inc()
method, the get()
method only reads the data without modifying it, meaning multiple threads could safely call it simultaneously.
What we actually want is the ability to allow multiple threads to read at the same time, but when a single thread is writing, all other threads must wait:
Operation | Read | Write |
---|---|---|
Read | Yes | No |
Write | No | No |
The ReadWriteLock
can solve this problem by ensuring:
- Only one thread can perform a write operation (other threads can neither write nor read).
- Multiple threads can read simultaneously when no write operation is in progress (improving performance).
Implementing this functionality with ReadWriteLock
is straightforward. We create a ReadWriteLock
instance and then obtain the read and write locks separately:
java
public class Counter {
private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
// Note: The read lock and write lock must be obtained from the same rwlock instance:
private final Lock rlock = rwlock.readLock();
private final Lock wlock = rwlock.writeLock();
private int[] counts = new int[10];
public void inc(int index) {
wlock.lock(); // Acquire the write lock
try {
counts[index] += 1;
} finally {
wlock.unlock(); // Release the write lock
}
}
public int[] get() {
rlock.lock(); // Acquire the read lock
try {
return Arrays.copyOf(counts, counts.length);
} finally {
rlock.unlock(); // Release the read lock
}
}
}
By using separate read and write locks, multiple threads can acquire the read lock simultaneously during read operations, greatly improving the efficiency of concurrent reads.
ReadWriteLock
is suitable when the same data is read frequently by many threads but modified by only a few.
For example, in a forum, posting a reply can be considered a write operation, which is infrequent, while viewing posts can be considered a read operation, which is very frequent. In such cases, ReadWriteLock
can be used.
Summary
Using ReadWriteLock
can improve read efficiency:
ReadWriteLock
allows only one thread to perform a write operation.ReadWriteLock
allows multiple threads to read simultaneously when there are no write operations.ReadWriteLock
is suitable for scenarios with many reads and few writes.