Java: синхронизированный метод в суперклассе получает такую ​​же блокировку, как и в подклассе, верно? - PullRequest
16 голосов
/ 09 марта 2009
class A {
    public synchronized void myOneMethod() {
        // ...
    }
}

class B extends A {
    public synchronized void myOtherMethod() {
        // ...
    }
}

// ...

B myObject;

// ...

myObject.myOneMethod(); // acquires lock
myObject.myOtherMethod(); // same lock?

Как я понимаю модель синхронизации, я бы сказал, что да, это так, потому что блокировка / монитор связаны с экземпляром myObject, и не имеет значения, где был определен метод. Но я прав? Если нет, то почему? Если да, то почему ты уверен, а я нет? : -)

Ответы [ 7 ]

12 голосов
/ 09 марта 2009

Да, вы правы, и вы тоже получили правильное объяснение. Больше нечего добавить.

Обратите внимание, что если бы методы были static , то они синхронизировались бы на разных объектах, а именно на их соответствующих классах (A и B).

РЕДАКТИРОВАТЬ : Почему я уверен? Я не знаю, почему ты не уверен? ;-) myObject - это всего лишь один объект - нет никаких различий между myObject атрибутами, полученными из класса A, и атрибутами, которые приходят из класса B. что, поэтому должно быть некоторое различие, но пока забудьте о рефлексии. Для обычных операций над объектом нет различия.)

7 голосов
/ 09 марта 2009

Да, синхронизированный эквивалентно синхронизированному (это).

Чтобы быть более точным :

Для метода класса (статического) используется блокировка, связанная с объектом Class для класса метода. Для метода экземпляра используется связанная с этим блокировка (объект, для которого был вызван метод).

3 голосов
/ 09 марта 2009

Если вы хотите более подробно рассказать о своей блокировке, вы можете сделать что-то вроде этого:

class A {

    protected final Object  mutex = new Object();
    public void myOneMethod() {
        synchronized (mutex) {
            // ...
        }
    }
}

class B extends A {
    public  void myOtherMethod() {
        synchronized (mutex) {
            // ...
        }
    }
}

Фактически, этот шаблон рекомендуется Брайаном Гетцем в Параллелизе Java на практике , раздел 4.2.1 «Шаблон монитора Java». Таким образом, вы точно знаете, откуда исходит ваш монитор.

1 голос
/ 09 марта 2009

Да. Java использует «мониторы» для реализации синхронизации, а синхронизированные методы используют экземпляр объекта, к которому они обращаются как монитор, что в данном случае, очевидно, одинаково.

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

0 голосов
/ 15 апреля 2015

С концептуальной точки зрения целостность мьютекса некоторых сценариев наследования будет нарушена, если synchonized методы класса A будут защищать данные A только в контексте подкласса B. В конце концов, не все данные A должны быть private.

Представьте, что вы хотите немного расширить функциональность одного из методов A, сохранив при этом остальные функции A, включая защиту мьютекса. Если бы A защищал только себя, вам пришлось бы переопределить все из A synchronized методов, чтобы поднять исходный механизм синхронизации в новый подкласс. Не очень привлекательно и не очень эффективно.

0 голосов
/ 12 июля 2010

Просто небольшое дополнение для людей, которые могут быть заинтересованы в будущем ..

Кроме того, помните, что блокировки в Java являются реентерабельными. Если бы их не было, ваш код привел бы к тупику, поскольку, как вы указали, обе операции требуют одинаковой блокировки.

0 голосов
/ 09 марта 2009

Да, вы правы

Когда один поток выполняет синхронизированный метод для объекта, все остальные потоки, которые вызывают синхронизированные методы для того же блока объекта (приостанавливают выполнение), пока первый поток не завершится с объектом. В этом случае объект B

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...