Класс ReentrantReadWriteLock
Класс ReentrantReadWriteLock из пакета java.util.concurrent.locks
представляет собой реализацию интерфейса ReadWriteLock.
Он хранит две связанные блокировки: одну для операций чтения
и одну для операций записи. Блокировка чтения может быть
захвачена одновременно несколькими потоками, если ни один
поток не удерживает блокировку записи. Блокировка записи
является эксклюзивной: пока ее удерживает один поток,
никакие другие потоки не могут захватить ни чтение, ни запись.
Обе блокировки являются реентерабельными, то есть поток
может повторно захватить уже удерживаемую им блокировку.
Конструктор класса принимает необязательный логический параметр,
который задает политику справедливости: при значении true
блокировки захватываются в порядке поступления запросов.
Основные методы: readLock возвращает блокировку чтения,
writeLock возвращает блокировку записи,
isFair проверяет политику справедливости,
getReadLockCount возвращает число удерживаемых блокировок чтения,
getWriteHoldCount возвращает число удержаний блокировки записи текущим потоком.
Синтаксис
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
Lock readLock = lock.readLock();
Lock writeLock = lock.writeLock();
Пример
Давайте создадим разделяемую переменную и защитим
ее чтение и запись с помощью ReentrantReadWriteLock.
Два потока читают значение, один поток записывает новое:
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.Lock;
public class Main
{
private static int sharedValue = 0;
private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public static void main(String[] args) throws InterruptedException
{
Runnable reader = () -> {
Lock readLock = lock.readLock();
readLock.lock();
try
{
System.out.println(Thread.currentThread().getName() + " read: " + sharedValue);
}
finally
{
readLock.unlock();
}
};
Runnable writer = () -> {
Lock writeLock = lock.writeLock();
writeLock.lock();
try
{
sharedValue = 100;
System.out.println(Thread.currentThread().getName() + " wrote: " + sharedValue);
}
finally
{
writeLock.unlock();
}
};
Thread t1 = new Thread(reader, "Reader-1");
Thread t2 = new Thread(reader, "Reader-2");
Thread t3 = new Thread(writer, "Writer-1");
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
}
Результат выполнения кода:
"Reader-1 read: 0"
"Reader-2 read: 0"
"Writer-1 wrote: 100"
Пример
Давайте проверим реентерабельность блокировки записи: поток дважды захватывает одну и ту же блокировку:
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.Lock;
public class Main
{
public static void main(String[] args)
{
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
Lock writeLock = lock.writeLock();
writeLock.lock();
try
{
System.out.println("Hold count after first lock: " + lock.getWriteHoldCount());
writeLock.lock();
try
{
System.out.println("Hold count after second lock: " + lock.getWriteHoldCount());
}
finally
{
writeLock.unlock();
}
}
finally
{
writeLock.unlock();
}
System.out.println("Hold count after unlock: " + lock.getWriteHoldCount());
}
}
Результат выполнения кода:
"Hold count after first lock: 1"
"Hold count after second lock: 2"
"Hold count after unlock: 0"
Пример
Давайте посмотрим, как блокировка чтения может быть захвачена несколькими потоками одновременно, а блокировка записи - только одним:
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.Lock;
public class Main
{
private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public static void main(String[] args) throws InterruptedException
{
Lock readLock = lock.readLock();
Lock writeLock = lock.writeLock();
readLock.lock();
try
{
System.out.println("Read lock count: " + lock.getReadLockCount());
readLock.lock();
try
{
System.out.println("Read lock count: " + lock.getReadLockCount());
}
finally
{
readLock.unlock();
}
}
finally
{
readLock.unlock();
}
System.out.println("Write lock is held: " + writeLock.toString().contains("Locked"));
}
}
Результат выполнения кода:
"Read lock count: 1"
"Read lock count: 2"
"Write lock is held: false"
Смотрите также
-
интерфейс
ReadWriteLock,
который реализует этот класс -
класс
ReentrantLock,
который представляет реентерабельную блокировку -
интерфейс
Lock,
который описывает базовые операции блокировки -
метод
unlock,
который освобождает блокировку