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

Вложенное синхронизированное ключевое слово

У меня есть этот код в Java:

    public void doSomeThing() {
        synchronized (this) {
            doSomeThingElse();
        }
    }
    public void doSomeThingElse() {
        synchronized (this) {
            // do something else
        }
    }

Может ли этот кодовый блок? Я имею в виду, может ли этот код ждать навсегда?

4b9b3361

Ответ 1

Как описывает java-документация для блокировки реентера:

поток может получить блокировку, чтобы она уже владеет

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

Нет, тупика не будет.

Ответ 2

Если поток владеет блокировкой на this, он перейдет в другие методы synchronized/блок, например, горячий нож в масле.

Ответ 3

В синхронизированном блоке вы можете повторно использовать блокировку, которой у вас уже есть. Поставщик блокировки (этот) будет получен первым потоком для ввода doSomething(). Затем в методе doSomethingElse() он повторно загрузит его.

Причина для этого? Ну, нечего сказать, что нет другого потока, входящего в doSomethingElse из другого места. Это предотвратит выполнение любым кодом кода в doSomething(), пока поток в doSomethingElse() не выпустит "this".

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

Ответ 4

Заблокировать уже obtanied потоком, выполняющим метод doSomething, поэтому этот поток может выполнить метод doSomethingElse.

Для создания ситуации взаимоблокировки требуется два объекта блокировки. В вашем случае есть только один, поэтому невозможно создать тупик.

Ответ 5

Синхронизированное использование в обоих случаях this, поэтому, если синхронизированный блок в doSomeThing выполняется, у вас уже есть блокировка, чтобы вы могли выполнить метод doSomeThingElse.

Если ваш код настолько прост, он эквивалентен:

public synchronized void doSomeThing() {
    doSomeThingElse();
}
public synchronized void doSomeThingElse() {
    // do something else
}

Ответ 6

Вы уже сделали блокировку монитора в первом синхронизированном состоянии. Вы всегда должны убедиться, что дизайн concurrency не сильно влияет на производительность.

Один из способов обеспечить это путем синхронизации только необходимых операторов/кода.

Скажем, теперь ваш код будет выглядеть примерно так.

public void doSomeThing()
 {
  synchronized (this) 
   {             
    synchronized (this) 
     {             
      // do something else         
     }           
   }     
 }

В то время как это то, что требуется

public void doSomeThing()
     {
       doSomeThingElse();     
     }
public void doSomeThingElse()
{
 synchronized (this) 
         {             
          // do something else         
         }
}