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

Статический и нестатический объект блокировки в синхронизированном блоке

Попытка визуализации и понимания синхронизации.

  • В чем разница между использованием объекта статической блокировки (код A) и объекта нестатического блокирования (код B) для синхронизированного блока?
  • Как он отличается в практических приложениях?
  • Каковы подводные камни, которые у других не было бы?
  • Каковы критерии для определения того, какой из них использовать?

Код A

public class MyClass1 {
  private static final Object lock = new Object();
  public MyClass1() {
    //unsync
    synchronized(lock) {
      //sync
    }
    //unsync
  }
}

Код B

public class MyClass2 {
  private final Object lock = new Object();
  public MyClass2() {
    //unsync
    synchronized(lock) {
      //sync
    }
    //unsync
  }
}

Примечание

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

Я уже смотрел ответы в на этот вопрос, но не достаточно ясно, каковы разные сценарии использования.

4b9b3361

Ответ 1

Разница проста: если заблокированный объект находится в поле static, то все экземпляры MyClass* будут разделять эту блокировку (т.е. ни один из двух объектов не сможет блокировать этот объект одновременно).

Если поле не статично, то каждый экземпляр будет иметь свою собственную блокировку, поэтому только вызовы метода на одном и том же объекте будут блокировать друг друга.

Когда вы используете объект статической блокировки:

  • поток 1 вызывает o1.foo()
  • thread 2 вызывает o1.foo(), придется ждать завершения потока 1
  • поток 3 вызова o2.foo(), также придется дождаться завершения потока 1 (и, вероятно, 2)

При использовании объекта нестатического блокировки:

  • поток 1 вызывает o1.foo()
  • thread 2 вызывает o1.foo(), придется ждать завершения потока 1
  • thread 3 calls o2.foo(), он может просто продолжить, не обращая внимания на темы 1 и 2

Какой из них вам понадобится, зависит от того, какие данные вы пытаетесь защитить с помощью синхронизированного блока.

Как правило, вы хотите, чтобы объект блокировки имел одинаковую static -ность, чем оперированное значение. Поэтому, если вы используете только нестатические значения, вам нужен объект нестатического блокирования. Если вы используете только статические значения, вам понадобится статический объект блокировки.

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

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