Подтвердить что ты не робот

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

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, и не имеет значения, где был определен метод. Но правильно? Если нет, то почему? Если да, то почему ты уверен, а я нет?: -)

4b9b3361

Ответ 1

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

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

EDIT: Почему я уверен? Я не знаю, почему ты не уверен?;-) myObject - это всего лишь один объект - нет никакого различия между атрибутами myObject, которые исходят из класса A и тех, которые приходят из класса B. (Ну, технически вы, вероятно, могли бы использовать отражение, чтобы узнать, какие что, следовательно, должно быть какое-то различие, но забыть об отражении на данный момент. Для общих операций над объектом нет различий.)

Ответ 2

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

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

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

Ответ 3

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

class A {

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

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

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

Ответ 4

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

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

Ответ 5

Да, вы правы.

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

Ответ 6

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

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

Ответ 7

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

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