В Java 5 появился интерфейс Lock
предоставляющий возможности более эффективного и тонкого контроля блокировки ресурсов. ReentrantLock
– распространённая реализация Lock
, которая предоставляет Lock
с таким же базовым поведением и семантикой, как у synchronized
, но расширенными возможностями, такими как опрос о блокировании (lock polling), ожидание блокирования заданной длительности и прерываемое ожидание блокировки. Кроме того, он предлагает гораздо более высокую эффективность функционирования в условиях жесткой состязательности.
Что понимается под блокировкой с повторным входом (reentrant)? Просто то, что есть подсчет сбора данных, связанный с блокировкой, и если поток, который удерживает блокировку, снова ее получает, данные отражают увеличение, и тогда для реального разблокирования нужно два раза снять блокировку. Это аналогично семантике synchronized; если поток входит в синхронный блок, защищенный монитором, который уже принадлежит потоку, потоку будет разрешено дальнейшее функционирование, и блокировка не будет снята, когда поток выйдет из второго (или последующего) блока synchronized, она будет снята только когда он выйдет из первого блока synchronized, в который он вошел под защитой монитора.
Lock lock = new ReentrantLock(); lock.lock(); try { // update object state } finally { lock.unlock(); }
- Реализация
ReentrantLock
гораздо более масштабируема в условиях состязательности, чем реализацияsynchronized
. Это значит, что когда много потоков соперничают за право получения блокировки, общая пропускная способность обычно лучше уReentrantLock
, чем уsynchronized
. JVM требуется меньше времени на установление очередности потоков и больше времени на непосредственно выполнение. - У
ReentrantLock
(как и у других реализацийLock
) блокировка должна обязательно сниматься вfinally
блоке (иначе, если бы защищенный код выбросил исключение, блокировка не была бы снята). Используя синхронизацию, JVM гарантирует, что блокировка автоматически снимаются.
Резюмируя, можно сказать, что когда состязания за блокировку нет либо оно очень мало, то synchronized
возможно будет быстрее. Если присутствует заметное состязание за доступ к ресурсу, то скорее всего ReentrantLock
даст некое преимущество.