Если у вас есть блокировка для объекта, у вас есть блокировка для всех его методов? - PullRequest
0 голосов
/ 11 февраля 2019

Скажем, у нас есть объект foo:

class Foo(){
  public synchronized void instanceMethod(){}
}

var foo = new Foo();

, если у меня есть блокировка для foo:

synchronized(foo){
  foo.instanceMethod();
}

У меня также есть блокировка на вызове instanceMethod()?Другой способ задать вопрос - если у меня есть блокировка для foo, может ли другой поток вызвать foo.instanceMethod () (одновременно)?

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019
class Foo {
    public synchronized void a() { //Do something }
    public void b() {
        synchronized(this) { // Do something }
    }
    public void c() { // Do something }
}

Тогда:

Foo foo = new Foo();
foo.a();
foo.b();
synchronized(foo) { foo.c(); }

Все 3 метода в значительной степени эквивалентны с точки зрения синхронизации.

Нет такой вещи, как "блокировка" метода.Блокировка производится только на объектах.Пометка метода synchronized просто заставляет его заблокировать экземпляр (или его объект класса для статического метода).

Когда вы обращаетесь к методу на заблокированном объекте, выполнение будет заблокировано, поскольку поток не сможет получить монитор для указанного объекта - это еще до вызова метода.Так что foo.a() будет заблокирован, когда он получит foo.

Добавление на ...

Я вдруг что-то вспомнил.Если у вас есть поток A, вызывающий foo.a(), и для его завершения требуется очень много времени, и в то время другой поток вызывает foo.c(), тогда foo.c() будет по-прежнему блокироваться до завершения foo.a().

0 голосов
/ 11 февраля 2019

если у меня есть блокировка для foo, может ли другой поток вызвать foo.instanceMethod ()?

Они могут вызвать его, но вызов будет ждать, пока выполнение не покинет ваш блок synchronized на foo, потому что instanceMethod равно synchronized.Объявление метода экземпляра synchronized - это примерно то же самое, что и помещение всего тела в блок synchronized на this.

Если instanceMethod не было синхронизировано, тоКонечно, вызов не будет ждать.

Обратите внимание, что показанный вами блок synchronized не нужен:

synchronized(foo){       // <==== Unnecessary
  foo.instanceMethod();
}

Поскольку instanceMethod равно synchronized, этоможет быть просто:

foo.instanceMethod();

... если только в блоке нет чего-то еще.

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