Вложенное синхронизированное ключевое слово - PullRequest
39 голосов
/ 03 февраля 2011

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

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

Может ли этот код блокировать? Я имею в виду, может ли этот код ждать вечно?

Ответы [ 6 ]

49 голосов
/ 03 февраля 2011

Как описывает Java-документация для Блокировка повторного входа :

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

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

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

8 голосов
/ 03 февраля 2011

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

3 голосов
/ 03 февраля 2011

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

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

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

1 голос
/ 03 февраля 2011

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

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

0 голосов
/ 03 февраля 2011

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

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

Допустим, теперь ваш код будет выглядетькак-то так.

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

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

public void doSomeThing()
     {
       doSomeThingElse();     
     }
public void doSomeThingElse()
{
 synchronized (this) 
         {             
          // do something else         
         }
}
0 голосов
/ 03 февраля 2011

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

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

public synchronized void doSomeThing() {
    doSomeThingElse();
}
public synchronized void doSomeThingElse() {
    // do something else
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...