Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗jvSpSyRl 203 of 322 menu
◀ ▶

Повторно входящий замок в Java

Класс ReentrantLock реализует Lock и считает, сколько раз один поток уже взял замок. Поток может вызвать lock() повторно, не заблокировав сам себя, пока не сделает столько же unlock().

Такое поведение похоже на вложенные synchronized методы одного объекта. Для явного замка удобно вызывать getHoldCount() и isHeldByCurrentThread() при отладке.

Два последовательных lock в одном потоке и один unlock оставляют монитор занятым:

import java.util.concurrent.locks.ReentrantLock; public class Main { private static final ReentrantLock gate = new ReentrantLock(); static void nested() { gate.lock(); try { gate.lock(); try { System.out.println(gate.getHoldCount()); } finally { gate.unlock(); } System.out.println(gate.getHoldCount()); } finally { gate.unlock(); } } public static void main(String[] args) { nested(); } }

Практический пример: приватный метод уже под замком, а публичный снова входит в ту же защиту:

import java.util.concurrent.locks.ReentrantLock; class Ledger { private final ReentrantLock gate = new ReentrantLock(); private int balance = 0; void add(int amount) { gate.lock(); try { balance += amount; } finally { gate.unlock(); } } void transferFrom(Ledger other, int amount) { gate.lock(); try { add(-amount); other.add(amount); } finally { gate.unlock(); } } int read() { gate.lock(); try { return balance; } finally { gate.unlock(); } } }

Внутренний add снова берет тот же ReentrantLock, и это безопасно. С обычным нерentrant замком такой вызов привел бы к взаимной блокировке.

ReentrantLock и поле level. Метод push увеличивает уровень под замком и вызывает pushAgain, который тоже берет замок. После двух вложенных вызовов уровень должен вырасти на 2.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить