Блокировка заказа - PullRequest
       41

Блокировка заказа

3 голосов
/ 10 марта 2010

С помощью следующего кода, если поток вызывает LoggingWidget.doSomething (), Каков порядок получения блокировки, через которую должен пройти поток? (т.е. получает ли он сначала блокировку на LoggingWidget, а затем получает блокировку на Widget?)

public class Widget {
   public synchronized void doSomething() {

   }
}

public class LoggingWidget extends Widget {
    public synchronized void doSomething() {
         System.out.println(toString() + ": calling doSomething");
         super.doSomething();
    }
}

Ответы [ 4 ]

3 голосов
/ 10 марта 2010

Блокировка в этом случае установлена ​​на this, поэтому существует только одна блокировка, которая является экземпляром. Если существует более одного экземпляра, каждый из них имеет совершенно отдельную блокировку независимо от того, Widget или LoggingWidget.

Позвольте мне сказать по-другому. Ваш код семантически эквивалентен:

public class Widget {
  public void doSomething() {
    synchronized (this) {
      // do stuff
    }
  }
}

public class LoggingWidget extends Widget {
  public void doSomething() {
    synchronized (this) {
      System.out.println(toString() + ": calling doSomething");
      super.doSomething();
    }
  }
}

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

1 голос
/ 26 мая 2014

Существует только одна блокировка, потому что есть только один объект , но если вызывается метод doSomething () объекта подкласса, одна и та же блокировка получается дважды. В JVM владелец (поток) тот же, но он устанавливает счетчик сбора в two . Счетчик получения уменьшается каждый раз, когда существует поток-владелец, синхронизированный блок . Таким образом, при окончательном снятии блокировки он будет уменьшен до нуля дважды, по одному на каждый синхронизированный блок.

1 голос
/ 10 марта 2010

В Java они являются мониторами Caleld и предназначены для каждого объекта. В вашем примере есть только один монитор.

0 голосов
/ 10 марта 2010

Если вы хотите убедиться, что вы получаете правильную блокировку типа LoggingWidget, а не Widget, вы можете сделать это:

public class LoggingWidget extends Widget {
  private final Object readLock = new Object();

  public void doSomething() {
    synchronized (readLock) {
      System.out.println(toString() + ": calling doSomething");
      super.doSomething();
    }
  }
}

Или, если вы используете Ломбок , вы можете просто написать

public class LoggingWidget extends Widget {
  @Synchronized("readLock")
  public void doSomething() {
    System.out.println(toString() + ": calling doSomething");
      super.doSomething();
  }
}
...