Spec-Zone.ru › OpenJDK 25

Интерфейс 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 имеет те же эффекты синхронизации памяти, что и успешное действие блокировки.
  • Успешная операция unlock имеет те же эффекты синхронизации памяти, что и успешное действие разблокировки.
Неуспешные операции блокировки и разблокировки, а также повторные операции блокировки и разблокировки не требуют каких-либо эффектов синхронизации памяти.

Особенности реализации

Три способа получения блокировки (с возможностью прерывания, без возможности прерывания и с тайм-аутом) могут различаться по производительности, гарантиям порядка или другим характеристикам реализации. Кроме того, в конкретном классе Lock может отсутствовать возможность прервать текущую попытку получения блокировки. Поэтому реализация не обязана предоставлять одинаковые гарантии или семантику для всех трёх способов получения блокировки и не обязана поддерживать прерывание текущей попытки получения блокировки. Реализация должна чётко документировать семантику и гарантии, предоставляемые каждым методом блокировки. Она также должна соблюдать семантику прерывания, определённую в этом интерфейсе, в той мере, в какой поддерживается прерывание получения блокировки: либо на протяжении всей операции, либо только при входе в метод.

Поскольку прерывание обычно подразумевает отмену, а проверка прерывания часто выполняется нечасто, реализация может предпочесть обработку прерывания обычному возврату из метода. Это справедливо, даже если можно показать, что прерывание произошло после того, как другое действие могло разблокировать поток. Реализации следует документировать такое поведение.

См. Спецификацию языка Java:
17.4 Модель памяти
Начиная с версии:
1.5
См. также:
  • ReentrantLock
  • Condition
  • ReadWriteLock

Краткое описание методов

Модификатор и тип Метод Описание
void lock()
Получает блокировку.
void lockInterruptibly()
Получает блокировку, если текущий поток не прерван.
Condition newCondition()
Возвращает новый экземпляр Condition, связанный с этим экземпляром Lock.
boolean tryLock()
Получает блокировку, только если на момент вызова она свободна.
boolean tryLock(long time, TimeUnit unit)
Получает блокировку, если она освободится в течение заданного времени ожидания и текущий поток не был прерван.
void unlock()
Освобождает блокировку.

Подробное описание методов

lock

void lock()
Получает блокировку.

Если блокировка недоступна, текущий поток приостанавливается для целей планирования потоков и ожидает, пока блокировка не будет получена.

Особенности реализации

Реализация Lock может обнаруживать неправильное использование блокировки, например вызов, приводящий к взаимоблокировке, и в таких случаях может выбросить (непроверяемое) исключение. Такая реализация Lock должна документировать условия возникновения исключения и его тип.

lockInterruptibly

void lockInterruptibly() throws InterruptedException
Получает блокировку, если текущий поток не прерван.

Если блокировка доступна, получает её и немедленно возвращает управление.

Если блокировка недоступна, текущий поток приостанавливается для целей планирования потоков и ожидает, пока не произойдёт одно из двух событий:

  • Текущий поток получит блокировку; или
  • Другой поток прервёт текущий поток, а прерывание получения блокировки поддерживается.

Если текущий поток:

  • входит в этот метод с установленным статусом прерывания; или
  • прерывается во время получения блокировки, а прерывание получения блокировки поддерживается,
то выбрасывается InterruptedException, а статус прерывания текущего потока сбрасывается.

Особенности реализации

В некоторых реализациях прервать получение блокировки может быть невозможно, а если это возможно, такая операция может быть затратной. Программисту следует учитывать такую возможность. Реализации следует документировать, поддерживается ли это.

Реализация может предпочесть обработку прерывания обычному возврату из метода.

Реализация Lock может обнаруживать неправильное использование блокировки, например вызов, приводящий к взаимоблокировке, и в таких случаях может выбросить (непроверяемое) исключение. Такая реализация Lock должна документировать условия возникновения исключения и его тип.

Выбрасывает:
InterruptedException — если текущий поток прерван во время получения блокировки (и поддерживается прерывание получения блокировки)

tryLock

boolean tryLock()
Получает блокировку, только если на момент вызова она свободна.

Если блокировка доступна, получает её и немедленно возвращает значение true. Если блокировка недоступна, этот метод немедленно возвращает значение false.

Типичный шаблон использования этого метода:

Lock lock = ...;
if (lock.tryLock()) {
  try {
    // manipulate protected state
  } finally {
    lock.unlock();
  }
} else {
  // perform alternative actions
}
Этот шаблон гарантирует, что блокировка будет освобождена, если она была получена, и что не будет предпринята попытка освободить её, если она не была получена.
Возвращает:
true, если блокировка была получена, и false в противном случае

tryLock

boolean tryLock(long time, TimeUnit unit) throws InterruptedException
Получает блокировку, если она освободится в течение заданного времени ожидания и текущий поток не был прерван.

Если блокировка доступна, этот метод немедленно возвращает значение true. Если блокировка недоступна, текущий поток приостанавливается для целей планирования потоков и ожидает, пока не произойдёт одно из трёх событий:

  • Текущий поток получит блокировку; или
  • Другой поток прервёт текущий поток, а прерывание получения блокировки поддерживается; или
  • Истечёт заданное время ожидания

Если блокировка получена, возвращается значение true.

Если текущий поток:

  • входит в этот метод с установленным статусом прерывания; или
  • прерывается во время получения блокировки, а прерывание получения блокировки поддерживается,
то выбрасывается InterruptedException, а статус прерывания текущего потока сбрасывается.

Если заданное время ожидания истекает, возвращается значение false. Если время меньше или равно нулю, метод не будет ждать.

Особенности реализации

В некоторых реализациях прервать получение блокировки может быть невозможно, а если это возможно, такая операция может быть затратной. Программисту следует учитывать такую возможность. Реализации следует документировать, поддерживается ли это.

Реализация может предпочесть обработку прерывания обычному возврату из метода или сообщению об истечении времени ожидания.

Реализация Lock может обнаруживать неправильное использование блокировки, например вызов, приводящий к взаимоблокировке, и в таких случаях может выбросить (непроверяемое) исключение. Такая реализация Lock должна документировать условия возникновения исключения и его тип.

Параметры:
time — максимальное время ожидания блокировки
unit — единица измерения времени для аргумента time
Возвращает:
true, если блокировка была получена, и false, если время ожидания истекло до получения блокировки
Выбрасывает:
InterruptedException — если текущий поток прерван во время получения блокировки (и поддерживается прерывание получения блокировки)

unlock

void unlock()
Освобождает блокировку.

Особенности реализации

Реализация Lock обычно устанавливает ограничения на то, какой поток может освободить блокировку (как правило, это может сделать только поток, удерживающий блокировку), и при нарушении ограничений может выбросить (непроверяемое) исключение. Такая реализация Lock должна документировать все ограничения и тип исключения.

newCondition

Condition newCondition()
Возвращает новый экземпляр Condition, связанный с этим экземпляром Lock.

Перед ожиданием условия текущий поток должен удерживать блокировку. Вызов Condition.await() атомарно освободит блокировку перед ожиданием и повторно получит её перед возвратом из ожидания.

Особенности реализации

Точное поведение экземпляра Condition зависит от реализации Lock и должно быть документировано этой реализацией.

Возвращает:
Новый экземпляр Condition для этого экземпляра Lock
Выбрасывает:
UnsupportedOperationException — если эта реализация Lock не поддерживает условия

Сообщить об ошибке или предложить улучшение
Дополнительную справочную информацию по API и документацию для разработчиков см. в документации Java SE, содержащей более подробные описания для разработчиков, обзоры концепций, определения терминов, обходные решения и примеры работающего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или её дочерних компаний в США и других странах.
Авторские права © 1993, 2025, Oracle и/или её дочерние компании, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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/Lock.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API