Блокировка повторного входа - параллелизм Java на практике

Вот пример кода для реентерабельной блокировки из статьи «Параллелизм Java на практике»:

class Widget {
public synchronized void doSomething() {
    System.out.println(toString() + ": calling superclass doSomething");
}


}

class LoggingWidget extends Widget {
public synchronized void doSomething() {
    System.out.println(toString() + ": calling subclass doSomething");
    super.doSomething();
}
}

В книге объясняется, что в приведенном выше коде ... «Поскольку методы doSomething в Widget и LoggingWidget оба синхронизированы, каждый из них пытается получить блокировку виджета, прежде чем продолжить».

Я запустил приведенный выше код, чтобы увидеть внутреннюю блокировку. Вышеприведенная цитата, по-видимому, подразумевает, что поток получает внутреннюю блокировку объекта Widget, но я заметил, что поток получает блокировку LoggingWidget. Я не знаю, как проверить количество приобретений, поэтому не мог этого наблюдать.

Использует ли книга имена LoggingWidget / Widget как взаимозаменяемые, или я должен специально наблюдать блокировку объекта Widget?

Изменить: полный отрывок

Повторная входимость облегчает инкапсуляцию поведения блокировки и, таким образом, упрощает разработку объектно-ориентированного параллельного кода. Без повторных блокировок очень естественно выглядящий код из Листинга 2.7, в котором подкласс переопределяет синхронизированный метод, а затем вызывает метод суперкласса, окажется в тупике. Поскольку методы doSomething в Widget и LoggingWidget оба синхронизированы, каждый из них пытается получить блокировку виджета перед продолжением. Но если внутренние блокировки не были реентерабельными, вызов super.doSomething никогда не смог бы получить блокировку, потому что он считался бы уже удерживаемым, и поток постоянно зависал бы в ожидании блокировки, которую он никогда не сможет получить. Повторная входимость спасает нас от тупика в подобных ситуациях.


person sotn    schedule 12.01.2015    source источник
comment
Тупик с одним потоком - для меня это выглядит странно   -  person gstackoverflow    schedule 08.02.2017


Ответы (2)


Да, автор использует LoggingWidget / Widget как взаимозаменяемые, потому что в соответствии с принципом наследования ООП объект LoggingWidget также является объектом класса Widget. В этом примере будет создан только один экземпляр объекта, который будет использоваться в качестве монитора синхронизации для повторного входа.

person Simon Sadetsky    schedule 12.01.2015

Мне нужно посмотреть отрывок, чтобы дать вам конкретный ответ. Вы можете создавать экземпляры этих классов по-разному. Блокировка удерживается на объекте, поэтому ссылка не имеет значения. Чтобы проиллюстрировать это ...

Эта структура классов очень похожа на вашу.

public class GenericTest {
    public static void main(String... args) {
        Sub sub = new Sub();
        sub.go();
    }

    public synchronized void go() {
        System.out.println("Parent");
    }
}

class Sub extends GenericTest {
    @Override
    public synchronized void go() {
        System.out.println("Child");
        super.go();
    }
}

Запустите эту программу и прекратите выполнение следующих строк после получения блокировки любым способом (например, System.in.read ()). Найдите pid-код java-программы и откройте его в Jconsole. Перейдите в раздел threads и выделяйте его каждый раз при получении блокировки. Вы увидите следующие следы.

my.package.common.GenericTest.go(GenericTest.java:30)
   - locked my.package.common.Sub@4c767286
my.package.common.Sub.go(GenericTest.java:42)
   - locked my.package.common.Sub@4c767286

Поскольку этот метод является переменной-членом, блокировка находится на текущем объекте (this), который выполнил рассматриваемый метод. Обратите внимание на то, что обе блокировки находятся на Sub@4c767286.

[РЕДАКТИРОВАТЬ]

Отредактировал свой ответ в соответствии с вашим конкретным случаем.

person Deepak Bala    schedule 12.01.2015
comment
Добавлен полный отрывок для ясности, но ваш ответ и ответ @ Semyon прояснили суть. К сожалению, в качестве ответа можно выбрать только один ответ. - person sotn; 13.01.2015