Интерфейс Lock
- Все известные реализующие классы:
-
ReentrantLock,ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock
public interface Lock
Lock реализации предоставляют более расширенные операции блокировки, чем можно получить, используя synchronized методы и операторы. Они позволяют более гибкую структуру, могут иметь совершенно разные свойства и могут поддерживать несколько связанных Condition объектов. Блокировка — инструмент для управления доступом к общему ресурсу несколькими потоками. Обычно блокировка обеспечивает эксклюзивный доступ к общему ресурсу: только один поток за раз может получить блокировку, и любой доступ к общему ресурсу требует предварительного получения блокировки. Однако некоторые блокировки могут разрешать одновременный доступ к общему ресурсу, например, чтение блокировки ReadWriteLock.
Использование synchronized методов или операторов обеспечивает доступ к неявной блокировке монитора, связанной с каждым объектом, но принуждает все получение и освобождение блокировки происходить в структурированном блоке: когда несколько блокировок приобретаются, они должны быть освобождены в обратном порядке, и все блокировки должны быть освобождены в той же лексической области, в которой они были получены.
Хотя механизм области действия для synchronized методов и операторов делает программирование с блокировками монитора намного проще и помогает избежать многих распространенных ошибок программирования, связанных с блокировками, есть случаи, когда вам нужно работать с блокировками более гибким способом. Например, некоторые алгоритмы для обхода одновременно доступных структур данных требуют использования «последовательного» или «цепного блокирования»: вы приобретаете блокировку узла A, затем узла B, затем освобождаете A и приобретаете C, затем освобождаете B и приобретаете D и так далее. Реализации интерфейса Lock позволяют использовать такие техники, позволяя получить и освободить блокировку в разных областях и позволять приобретать и освобождать несколько блокировок в любом порядке.
С этим увеличением гибкости появляется дополнительная ответственность. Отсутствие структурированного по блокам блокирования удаляет автоматическое освобождение блокировок, которое происходит с synchronized методами и операторами. В большинстве случаев следует использовать следующий шаблон:
Lock l = ...;
l.lock(); // lock() as the last statement before the try block
try {
// access the resource protected by this lock
} finally {
l.unlock(); // unlock() as the first statement in the finally block
} При блокировании и разблокировании в разных областях необходимо следить за тем, чтобы весь код, выполняемый, пока блокировка удерживается, был защищен try-finally или try-catch, чтобы гарантировать освобождение блокировки при необходимости. Lock реализации предоставляют дополнительную функциональность по сравнению с использованием synchronized методов и операторов, предоставляя неудачную попытку получения блокировки (tryLock()), попытку получения блокировки, которую можно прервать (lockInterruptibly()) и попытку получения блокировки, которая может истечь (tryLock(long, TimeUnit)).
Класс Lock также может предоставить поведение и семантику, которая значительно отличается от неявной блокировки монитора, например, гарантированный порядок, нерекурсивное использование или обнаружение тупиков. Если реализация предоставляет такую специализированную семантику, реализация должна документировать эту семантику.
Обратите внимание, что экземпляры Lock — это просто обычные объекты и могут сами использоваться в качестве цели в операторе synchronized. Получение блокировки монитора экземпляра Lock не имеет заданной взаимосвязи с вызовом методов lock() этого экземпляра. Рекомендуется, чтобы избежать путаницы, вы никогда не использовали экземпляры Lock таким образом, кроме как в своей собственной реализации.
За исключением случаев, оговоренных в отдельности, передача значения null для любого параметра приведет к выбросу NullPointerException.
Синхронизация памяти
Все Lock реализации обязаны обеспечивать те же семантики синхронизации памяти, что и встроенная блокировка монитора, как описано в главе 17 спецификации языка Java:
- Успешная операция
lockимеет те же эффекты синхронизации памяти, что и успешное действие Lock. - Успешная операция
unlockимеет те же эффекты синхронизации памяти, что и успешное действие Unlock.
Соображения по реализации
Три формы получения блокировки (прерываемая, непрерывная и с тайм-аутом) могут отличаться по производительности, гарантиям порядка или другим характеристикам реализации. Кроме того, возможность прервать процесс получения блокировки может отсутствовать в данном классе Lock. Следовательно, реализация не обязана определять точно те же гарантии или семантику для всех трех форм получения блокировки, ни не обязана поддерживать прерывание текущего процесса получения блокировки. Реализация должна четко документировать семантику и гарантии, предоставляемые каждым из методов блокировки. Она также должна соблюдать семантику прерывания, как определено в этом интерфейсе, в той мере, в которой поддерживается прерывание получения блокировки: полностью или только при входе в метод.
Поскольку прерывание обычно подразумевает отмену, а проверки на прерывание часто нечастые, реализация может отдавать предпочтение реагированию на прерывание перед обычным возвратом из метода. Это верно, даже если можно показать, что прерывание произошло после того, как другой процесс может разблокировать поток. Реализация должна документировать это поведение.
- См. Спецификацию языка Java:
- 17.4 Модель памяти
- С момента:
- 1.5
- См. также:
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
void |
lock() |
Получает блокировку. |
void |
lockInterruptibly() |
Получает блокировку, если текущий поток не прерван. |
Condition |
newCondition() |
Возвращает новый Condition экземпляр, привязанный к этому экземпляру Lock. |
boolean |
tryLock() |
Получает блокировку только если она свободна в момент вызова. |
boolean |
tryLock |
Получает блокировку, если она свободна в течение заданного времени ожидания, и текущий поток не прерван. |
void |
unlock() |
Освобождает блокировку. |
Подробное описание методов
lock
void lock()
Если блокировка недоступна, текущий поток становится неактивным для целей планирования потоков и находится в ожидании, пока блокировка не будет захвачена.
Соображения по реализации
Реализация Lock может обнаруживать ошибочное использование блокировки, например, вызов, который приведет к тупику, и в таких случаях может выбросить (непроверенное) исключение. Обстоятельства и тип исключения должны быть задокументированы реализацией Lock.
lockInterruptibly
void lockInterruptibly() throws InterruptedException
Захватывает блокировку, если она доступна, и возвращает результат немедленно.
Если блокировка недоступна, текущий поток становится неактивным для целей планирования потоков и находится в ожидании, пока не произойдёт одно из двух событий:
- Текущий поток захватывает блокировку; или
- Другой поток прерывает текущий поток, и прерывание процесса захвата блокировки поддерживается.
Если у текущего потока:
- Флаг прерывания установлен при входе в этот метод; или
- Поток прерывается во время захвата блокировки, и прерывание процесса захвата блокировки поддерживается,
InterruptedException, и флаг прерывания текущего потока сбрасывается. Соображения по реализации
Возможность прервать захват блокировки в некоторых реализациях может отсутствовать или быть дорогостоящей операцией. Разработчик должен быть об этом осведомлён. Реализация должна документировать подобные случаи.
Реализация может отдавать приоритет обработке прерывания перед обычным возвратом метода.
Реализация Lock может обнаруживать ошибочное использование блокировки, например, вызов, который приведет к тупику, и в таких случаях может выбросить (непроверенное) исключение. Обстоятельства и тип исключения должны быть задокументированы реализацией Lock.
- Throws:
-
InterruptedException- если текущий поток прерывается во время захвата блокировки (и прерывание захвата блокировки поддерживается)
tryLock
boolean tryLock()
Захватывает блокировку, если она доступна, и немедленно возвращает значение true. Если блокировка недоступна, этот метод немедленно возвращает значение false.
Типичный шаблон использования этого метода:
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
} Это использование гарантирует, что блокировка разблокирована, если она была захвачена, и не пытается разблокировать её, если блокировка не была захвачена.- Returns:
-
true, если блокировка была захвачена, иfalseв противном случае
tryLock
boolean tryLock(long time, TimeUnit unit) throws InterruptedException
Если блокировка доступна, этот метод возвращает значение true немедленно. Если блокировка недоступна, текущий поток становится неактивным для целей планирования потоков и находится в ожидании, пока не произойдёт одно из трёх событий:
- Текущий поток захватывает блокировку; или
- Другой поток прерывает текущий поток, и прерывание процесса захвата блокировки поддерживается; или
- Заданное время ожидания истекает
Если блокировка захвачена, возвращается значение true.
Если у текущего потока:
- Флаг прерывания установлен при входе в этот метод; или
- Поток прерывается во время захвата блокировки, и прерывание процесса захвата блокировки поддерживается,
InterruptedException, и флаг прерывания текущего потока сбрасывается. Если заданное время ожидания истекает, возвращается значение false. Если время равно или меньше нуля, метод не будет ожидать.
Соображения по реализации
Возможность прервать захват блокировки в некоторых реализациях может отсутствовать или быть дорогостоящей операцией. Разработчик должен быть об этом осведомлён. Реализация должна документировать подобные случаи.
Реализация может отдавать приоритет обработке прерывания перед обычным возвратом метода или сообщением о тайм-ауте.
Реализация Lock может обнаруживать ошибочное использование блокировки, например, вызов, который приведет к тупику, и в таких случаях может выбросить (непроверенное) исключение. Обстоятельства и тип исключения должны быть задокументированы реализацией Lock.
- Parameters:
-
time- максимальное время ожидания блокировки -
unit- единица измерения времени для аргументаtime - Returns:
-
true, если блокировка была захвачена, иfalse, если время ожидания истекло до захвата блокировки - Throws:
-
InterruptedException- если текущий поток прерывается во время захвата блокировки (и прерывание захвата блокировки поддерживается)
unlock
void unlock()
Соображения по реализации
Реализация Lock обычно накладывает ограничения на тот поток, который может освободить блокировку (обычно только владелец блокировки может её освободить) и может выбросить (непроверенное) исключение, если ограничение нарушено. Любые ограничения и тип исключения должны быть задокументированы реализацией Lock.
newCondition
Condition newCondition()
Condition, связанную с этим экземпляром Lock. Перед ожиданием условия текущий поток должен удерживать блокировку. Вызов Condition.await() атомарно освобождает блокировку перед ожиданием и повторно захватывает блокировку перед возвратом из ожидания.
Соображения по реализации
Точное поведение экземпляра Condition зависит от реализации Lock и должно быть задокументировано этой реализацией.
- Returns:
- Новый экземпляр
Conditionдля этого экземпляраLock - Throws:
-
UnsupportedOperationException- если реализацияLockне поддерживает условия
© 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://download.java.net/java/early_access/jdk24/docs/api/java.base/java/util/concurrent/locks/Lock.html