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