Чем полезно значение 'hold count' в Reentrant Lock?

Reentrant Lock ( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html) имеет функцию для определения силы блокировки определенным потоком, которая основана на значение "счетчик удержаний". Он инициализируется, когда поток получает блокировку, и каждый раз, когда он повторно блокирует блокировку, значение увеличивается. Значение уменьшается каждый раз, когда поток вызывает метод разблокировки блокировки.

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

Какова полезность отсчета удержания? Каковы варианты использования этого? Одним из таких вариантов использования может быть проверка текущего потока, удерживающего блокировку (значение счетчика удержания> 0). Но есть разные API, такие как isHeldByCurrentThread(),

2 ответа

Решение

Документация API для этого метода объясняет это:

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

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

Предположим, у вас есть метод, включающий заблокированный блок, вы можете вызвать его из другого места. Этот метод должен делать разные вещи в зависимости от количества блокировок. Тогда вы можете использовать getHoldCount,

import java.util.concurrent.locks.ReentrantLock;

public class Example {

    ReentrantLock lock = new ReentrantLock();

    void method1() {
        lock.lock();
        try {
            if (lock.getHoldCount() == 1) { 
                System.out.println("call method1 directly");
            } else if (lock.getHoldCount() == 2) {
                System.out.println("call method1 from method2");
            }
        } finally {
            lock.unlock();
        }
    }

    void method2() {
        lock.lock();
        try {
            method1();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        Example example = new Example();
        example.method1(); // call method1 directly
        example.method2();  // call method2 from method2
    }
}
Другие вопросы по тегам