Класс StampedLock
- Все реализуемые интерфейсы:
Serializable
public class StampedLock extends Object implements Serializable
-
Запись. Метод
writeLock()может блокировать поток в ожидании эксклюзивного доступа и возвращает штамп, который можно использовать в методеunlockWrite(long)для снятия блокировки. Также доступны версииtryWriteLockбез ограничения времени ожидания и с ограничением времени ожидания. Когда блокировка удерживается в режиме записи, получить блокировки чтения нельзя, а все проверки оптимистичного чтения завершаются неудачей. -
Чтение. Метод
readLock()может блокировать поток в ожидании неэксклюзивного доступа и возвращает штамп, который можно использовать в методеunlockRead(long)для снятия блокировки. Также доступны версииtryReadLockбез ограничения времени ожидания и с ограничением времени ожидания. -
Оптимистичное чтение. Метод
tryOptimisticRead()возвращает ненулевой штамп, только если блокировка в данный момент не удерживается в режиме записи. Методvalidate(long)возвращает true, если после получения заданного штампа блокировка не захватывалась в режиме записи; в этом случае все действия, предшествующие последнему освобождению блокировки записи, происходят-before действий, следующих за вызовомtryOptimisticRead. Этот режим можно считать крайне ослабленной версией блокировки чтения, которую записывающий поток может прервать в любой момент. Использование режима оптимистичного чтения для коротких сегментов кода, выполняющих только чтение, часто снижает конкуренцию и повышает пропускную способность. Однако его использование по своей природе ненадёжно. В секциях оптимистичного чтения следует только считывать поля и сохранять их в локальных переменных для последующего использования после проверки. Значения полей, прочитанные в режиме оптимистичного чтения, могут быть крайне несогласованными, поэтому этот режим следует использовать только в том случае, если вы достаточно хорошо знакомы с представлением данных, чтобы проверять согласованность и/или многократно вызывать методvalidate(). Например, такие шаги обычно необходимы, когда сначала считывается ссылка на объект или массив, а затем выполняется обращение к одному из его полей, элементов или методов.
Этот класс также поддерживает методы, условно преобразующие блокировку между тремя режимами. Например, метод tryConvertToWriteLock(long) пытается «повысить» режим, возвращая действительный штамп записи, если выполняется одно из условий: (1) блокировка уже находится в режиме записи; (2) блокировка находится в режиме чтения и других читателей нет; или (3) блокировка находится в режиме оптимистичного чтения и доступна. Формы этих методов разработаны, чтобы сократить разрастание кода, которое иначе возникает при использовании схем на основе повторных попыток.
StampedLock предназначены для использования в качестве внутренних вспомогательных средств при разработке потокобезопасных компонентов. Их применение основано на знании внутренних свойств защищаемых данных, объектов и методов. Они не являются реентерабельными, поэтому код внутри блокировки не должен вызывать другие неизвестные методы, которые могут попытаться повторно захватить блокировки (хотя штамп можно передать другим методам, которые могут использовать его или преобразовать). Использование режимов блокировки чтения предполагает, что соответствующие секции кода не имеют побочных эффектов. В секциях оптимистичного чтения без проверки нельзя вызывать методы, которые не гарантируют корректную работу при возможной несогласованности данных. Штампы имеют конечное представление и не являются криптографически защищёнными (то есть действительный штамп можно угадать). Значения штампов могут повторно использоваться после (но не ранее чем через) одного года непрерывной работы. Штамп, хранящийся без использования или проверки дольше этого периода, может не пройти проверку корректно. StampedLock сериализуемы, но всегда десериализуются в исходное незаблокированное состояние, поэтому не подходят для удалённой блокировки.
Подобно Semaphore, но в отличие от большинства реализаций Lock, StampedLock не имеют понятия владения. Блокировки, захваченные в одном потоке, можно освободить или преобразовать в другом.
Политика планирования StampedLock не отдаёт постоянного предпочтения ни читателям, ни записывающим потокам. Все методы с префиксом «try» работают по возможности и не обязательно соответствуют какой-либо политике планирования или справедливости. Возвращаемый любым методом «try» для захвата или преобразования блокировки ноль не содержит информации о состоянии блокировки; следующий вызов может завершиться успешно.
Поскольку этот класс поддерживает согласованное использование нескольких режимов блокировки, он напрямую не реализует интерфейсы Lock или ReadWriteLock. Однако в приложениях, которым нужен только соответствующий набор функций, StampedLock можно представить как asReadLock(), asWriteLock() или asReadWriteLock().
Синхронизация памяти. Методы, успешно захватывающие блокировку в любом режиме, имеют те же эффекты синхронизации памяти, что и действие Lock, описанное в главе 17 Спецификации языка Java. Методы, успешно освобождающие блокировку в режиме записи, имеют те же эффекты синхронизации памяти, что и действие Unlock. При использовании оптимистичного чтения действия, предшествующие последнему действию освобождения блокировки в режиме записи, гарантированно происходят-before действий, следующих за tryOptimisticRead, только если последующий вызов validate возвращает true; в противном случае нет гарантии, что чтения между tryOptimisticRead и validate дают согласованный снимок.
Пример использования. Ниже показаны некоторые идиомы использования в классе, который хранит простые двумерные точки. В примере кода показаны некоторые соглашения по использованию try/catch, хотя здесь они не строго необходимы, поскольку в теле блоков не может возникнуть исключений.
class Point {
private double x, y;
private final StampedLock sl = new StampedLock();
// an exclusively locked method
void move(double deltaX, double deltaY) {
long stamp = sl.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
sl.unlockWrite(stamp);
}
}
// a read-only method
// upgrade from optimistic read to read lock
double distanceFromOrigin() {
long stamp = sl.tryOptimisticRead();
try {
retryHoldingLock: for (;; stamp = sl.readLock()) {
if (stamp == 0L)
continue retryHoldingLock;
// possibly racy reads
double currentX = x;
double currentY = y;
if (!sl.validate(stamp))
continue retryHoldingLock;
return Math.hypot(currentX, currentY);
}
} finally {
if (StampedLock.isReadLockStamp(stamp))
sl.unlockRead(stamp);
}
}
// upgrade from optimistic read to write lock
void moveIfAtOrigin(double newX, double newY) {
long stamp = sl.tryOptimisticRead();
try {
retryHoldingLock: for (;; stamp = sl.writeLock()) {
if (stamp == 0L)
continue retryHoldingLock;
// possibly racy reads
double currentX = x;
double currentY = y;
if (!sl.validate(stamp))
continue retryHoldingLock;
if (currentX != 0.0 || currentY != 0.0)
break;
stamp = sl.tryConvertToWriteLock(stamp);
if (stamp == 0L)
continue retryHoldingLock;
// exclusive access
x = newX;
y = newY;
return;
}
} finally {
if (StampedLock.isWriteLockStamp(stamp))
sl.unlockWrite(stamp);
}
}
// upgrade read lock to write lock
void moveIfAtOrigin2(double newX, double newY) {
long stamp = sl.readLock();
try {
while (x == 0.0 && y == 0.0) {
long ws = sl.tryConvertToWriteLock(stamp);
if (ws != 0L) {
stamp = ws;
x = newX;
y = newY;
break;
}
else {
sl.unlockRead(stamp);
stamp = sl.writeLock();
}
}
} finally {
sl.unlock(stamp);
}
}
}
- См. Спецификацию языка Java:
- 17.4 Модель памяти
- Начиная с версии:
- 1.8
- См. также:
Краткое описание конструкторов
| Конструктор | Описание |
|---|---|
StampedLock() |
Создаёт новую блокировку, изначально находящуюся в незаблокированном состоянии. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
Lock |
asReadLock() |
Возвращает обычное представление этого StampedLock в виде Lock, в котором метод Lock.lock() сопоставлен с readLock(), и аналогично для других методов. |
ReadWriteLock |
asReadWriteLock() |
Возвращает представление этого StampedLock в виде ReadWriteLock, в котором метод ReadWriteLock.readLock() сопоставлен с asReadLock(), а метод ReadWriteLock.writeLock() — с asWriteLock(). |
Lock |
asWriteLock() |
Возвращает обычное представление этого StampedLock в виде Lock, в котором метод Lock.lock() сопоставлен с writeLock(), и аналогично для других методов. |
int |
getReadLockCount() |
Возвращает количество удерживаемых блокировок чтения для этой блокировки. |
static boolean |
isLockStamp |
Определяет, означает ли штамп, что блокировка удерживается. |
static boolean |
isOptimisticReadStamp |
Определяет, означает ли штамп успешное оптимистичное чтение. |
boolean |
isReadLocked() |
Возвращает true, если в данный момент блокировка удерживается неэксклюзивно. |
static boolean |
isReadLockStamp |
Определяет, означает ли штамп, что блокировка удерживается неэксклюзивно. |
boolean |
isWriteLocked() |
Возвращает true, если в данный момент блокировка удерживается эксклюзивно. |
static boolean |
isWriteLockStamp |
Определяет, означает ли штамп, что блокировка удерживается эксклюзивно. |
long |
readLock() |
Захватывает блокировку неэксклюзивно, при необходимости блокируя поток до её освобождения. |
long |
readLockInterruptibly() |
Захватывает блокировку неэксклюзивно, при необходимости блокируя поток до её освобождения или прерывания текущего потока. |
String |
toString() |
Возвращает строку, идентифицирующую эту блокировку и её состояние. |
long |
tryConvertToOptimisticRead |
Если состояние блокировки соответствует заданному штампу, атомарно освобождает блокировку, если штамп означает, что она удерживается, и возвращает штамп наблюдения. |
long |
tryConvertToReadLock |
Если состояние блокировки соответствует заданному штампу, атомарно выполняет одно из следующих действий. |
long |
tryConvertToWriteLock |
Если состояние блокировки соответствует заданному штампу, атомарно выполняет одно из следующих действий. |
long |
tryOptimisticRead() |
Возвращает штамп, который впоследствии можно проверить, или ноль, если блокировка захвачена эксклюзивно. |
long |
tryReadLock() |
Захватывает блокировку неэксклюзивно, если она доступна немедленно. |
long |
tryReadLock |
Захватывает блокировку неэксклюзивно, если она становится доступна в течение заданного времени и текущий поток не был прерван. |
boolean |
tryUnlockRead() |
Освобождает одно удержание блокировки чтения, если она захвачена, без необходимости указывать значение штампа. |
boolean |
tryUnlockWrite() |
Освобождает блокировку записи, если она захвачена, без необходимости указывать значение штампа. |
long |
tryWriteLock() |
Захватывает блокировку эксклюзивно, если она доступна немедленно. |
long |
tryWriteLock |
Захватывает блокировку эксклюзивно, если она становится доступна в течение заданного времени и текущий поток не был прерван. |
void |
unlock |
Если состояние блокировки соответствует заданному штампу, освобождает блокировку в соответствующем режиме. |
void |
unlockRead |
Если состояние блокировки соответствует заданному штампу, освобождает неэксклюзивную блокировку. |
void |
unlockWrite |
Если состояние блокировки соответствует заданному штампу, освобождает эксклюзивную блокировку. |
boolean |
validate |
Возвращает true, если после выдачи заданного штампа блокировка не захватывалась эксклюзивно. |
long |
writeLock() |
Захватывает блокировку эксклюзивно, при необходимости блокируя поток до её освобождения. |
long |
writeLockInterruptibly() |
Захватывает блокировку эксклюзивно, при необходимости блокируя поток до её освобождения или прерывания текущего потока. |
Подробное описание конструкторов
StampedLock
public StampedLock()
Подробное описание методов
writeLock
public long writeLock()
- Возвращает:
- штамп записи, который можно использовать для снятия блокировки или преобразования режима
tryWriteLock
public long tryWriteLock()
- Возвращает:
- штамп записи, который можно использовать для снятия блокировки или преобразования режима, либо ноль, если блокировка недоступна
tryWriteLock
public long tryWriteLock(long time, TimeUnit unit) throws InterruptedException
Lock.tryLock(long,TimeUnit).- Параметры:
-
time— максимальное время ожидания блокировки -
unit— единица измерения аргументаtime - Возвращает:
- штамп записи, который можно использовать для снятия блокировки или преобразования режима, либо ноль, если блокировка недоступна
- Выбрасывает:
-
InterruptedException— если текущий поток прерван до захвата блокировки
writeLockInterruptibly
public long writeLockInterruptibly() throws InterruptedException
Lock.lockInterruptibly().- Возвращает:
- штамп записи, который можно использовать для снятия блокировки или преобразования режима
- Выбрасывает:
-
InterruptedException— если текущий поток прерван до захвата блокировки
readLock
public long readLock()
- Возвращает:
- штамп чтения, который можно использовать для снятия блокировки или преобразования режима
tryReadLock
public long tryReadLock()
- Возвращает:
- штамп чтения, который можно использовать для снятия блокировки или преобразования режима, либо ноль, если блокировка недоступна
tryReadLock
public long tryReadLock(long time, TimeUnit unit) throws InterruptedException
Lock.tryLock(long,TimeUnit).- Параметры:
-
time— максимальное время ожидания блокировки -
unit— единица измерения аргументаtime - Возвращает:
- штамп чтения, который можно использовать для снятия блокировки или преобразования режима, либо ноль, если блокировка недоступна
- Выбрасывает:
-
InterruptedException— если текущий поток прерван до захвата блокировки
readLockInterruptibly
public long readLockInterruptibly() throws InterruptedException
Lock.lockInterruptibly().- Возвращает:
- штамп чтения, который можно использовать для снятия блокировки или преобразования режима
- Выбрасывает:
-
InterruptedException— если текущий поток прерван до захвата блокировки
tryOptimisticRead
public long tryOptimisticRead()
- Возвращает:
- действительный штамп оптимистического чтения или ноль, если блокировка захвачена эксклюзивно
validate
public boolean validate(long stamp)
tryOptimisticRead() или метода захвата блокировки для этой блокировки, не имеет определенного эффекта или результата.- Параметры:
-
stamp— штамп - Возвращает:
-
true, если после выдачи указанного штампа блокировка не захватывалась эксклюзивно; в противном случае false
unlockWrite
public void unlockWrite(long stamp)
- Параметры:
-
stamp— штамп, возвращенный операцией захвата блокировки на запись - Выбрасывает:
-
IllegalMonitorStateException— если штамп не соответствует текущему состоянию этой блокировки
unlockRead
public void unlockRead(long stamp)
- Параметры:
-
stamp— штамп, возвращенный операцией захвата блокировки на чтение - Выбрасывает:
-
IllegalMonitorStateException— если штамп не соответствует текущему состоянию этой блокировки
unlock
public void unlock(long stamp)
- Параметры:
-
stamp— штамп, возвращенный операцией захвата блокировки - Выбрасывает:
-
IllegalMonitorStateException— если штамп не соответствует текущему состоянию этой блокировки
tryConvertToWriteLock
public long tryConvertToWriteLock(long stamp)
- Параметры:
-
stamp— штамп - Возвращает:
- действительный штамп записи или ноль в случае неудачи
tryConvertToReadLock
public long tryConvertToReadLock(long stamp)
- Параметры:
-
stamp— штамп - Возвращает:
- действительный штамп чтения или ноль в случае неудачи
tryConvertToOptimisticRead
public long tryConvertToOptimisticRead(long stamp)
- Параметры:
-
stamp— штамп - Возвращает:
- действительный штамп оптимистического чтения или ноль в случае неудачи
tryUnlockWrite
public boolean tryUnlockWrite()
- Возвращает:
-
true, если блокировка была захвачена; в противном случае false
tryUnlockRead
public boolean tryUnlockRead()
- Возвращает:
-
true, если блокировка на чтение была захвачена; в противном случае false
isWriteLocked
public boolean isWriteLocked()
true, если в данный момент блокировка удерживается эксклюзивно.- Возвращает:
-
true, если в данный момент блокировка удерживается эксклюзивно
isReadLocked
public boolean isReadLocked()
true, если в данный момент блокировка удерживается неэксклюзивно.- Возвращает:
-
true, если в данный момент блокировка удерживается неэксклюзивно
isWriteLockStamp
public static boolean isWriteLockStamp(long stamp)
tryConvertToWriteLock(long), например: long stamp = sl.tryOptimisticRead();
try {
...
stamp = sl.tryConvertToWriteLock(stamp);
...
} finally {
if (StampedLock.isWriteLockStamp(stamp))
sl.unlockWrite(stamp);
}
- Параметры:
-
stamp— штамп, возвращенный предыдущей операцией StampedLock - Возвращает:
-
true, если штамп был возвращен успешной операцией захвата блокировки на запись - Начиная с версии:
- 10
isReadLockStamp
public static boolean isReadLockStamp(long stamp)
tryConvertToReadLock(long), например: long stamp = sl.tryOptimisticRead();
try {
...
stamp = sl.tryConvertToReadLock(stamp);
...
} finally {
if (StampedLock.isReadLockStamp(stamp))
sl.unlockRead(stamp);
}
- Параметры:
-
stamp— штамп, возвращенный предыдущей операцией StampedLock - Возвращает:
-
true, если штамп был возвращен успешной операцией захвата блокировки на чтение - Начиная с версии:
- 10
isLockStamp
public static boolean isLockStamp(long stamp)
tryConvertToReadLock(long) и tryConvertToWriteLock(long), например: long stamp = sl.tryOptimisticRead();
try {
...
stamp = sl.tryConvertToReadLock(stamp);
...
stamp = sl.tryConvertToWriteLock(stamp);
...
} finally {
if (StampedLock.isLockStamp(stamp))
sl.unlock(stamp);
}
- Параметры:
-
stamp— штамп, возвращенный предыдущей операцией StampedLock - Возвращает:
-
true, если штамп был возвращен успешной операцией захвата блокировки на чтение или запись - Начиная с версии:
- 10
isOptimisticReadStamp
public static boolean isOptimisticReadStamp(long stamp)
- Параметры:
-
stamp— штамп, возвращенный предыдущей операцией StampedLock - Возвращает:
-
true, если штамп был возвращен успешной операцией оптимистического чтения, то есть ненулевым результатом вызоваtryOptimisticRead()илиtryConvertToOptimisticRead(long) - Начиная с версии:
- 10
getReadLockCount
public int getReadLockCount()
- Возвращает:
- количество удерживаемых блокировок на чтение
toString
public String toString()
"Unlocked", строку "Write-locked" или строку "Read-locks:", за которой следует текущее количество удерживаемых блокировок на чтение.asReadLock
public Lock asReadLock()
Lock, в котором метод Lock.lock() сопоставлен с readLock(), как и другие методы. Возвращенный Lock не поддерживает Condition; метод Lock.newCondition() выбрасывает UnsupportedOperationException.- Возвращает:
- блокировку
asWriteLock
public Lock asWriteLock()
Lock, в котором метод Lock.lock() сопоставлен с writeLock(), как и другие методы. Возвращенный Lock не поддерживает Condition; метод Lock.newCondition() выбрасывает UnsupportedOperationException.- Возвращает:
- блокировку
asReadWriteLock
public ReadWriteLock asReadWriteLock()
ReadWriteLock, в котором метод ReadWriteLock.readLock() сопоставлен с asReadLock(), а метод ReadWriteLock.writeLock() — с asWriteLock().- Возвращает:
- блокировку
© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/locks/StampedLock.html