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

В чем разница между синхронизированным (это) и синхронизированным (ClassName.class)?

Я где-то читал, что synchronized(this) следует избегать для различных причин. Однако какой-то респектабельный код, с которым я столкнулся, использует в конструкторе следующее:

public SomeClass(Context context) {
  if (double_checked_lock == null) {
    synchronized (SomeClass.class) {
      if (double_checked_lock == null) {
        // some code here
      }
    }
  }
}

Есть ли разница между synchronized(this) и synchronized(SomeClass.class)?

4b9b3361

Ответ 1

synchronized(this) синхронизируется с текущим объектом, поэтому только один поток может обращаться к каждому экземпляру, но разные потоки могут обращаться к различным экземплярам. Например. вы можете иметь один экземпляр для потока.

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

synchronized(SomeClass.class) синхронизируется по классу текущего объекта (или другого класса, если хотите), поэтому только один поток за один раз может обращаться к любым экземплярам этого класса.

Это может быть использовано для защиты данных, которые совместно используются для всех экземпляров класса (например, кеша экземпляра), от попадания в несогласованное состояние.

Ответ 2

this отличается для каждого экземпляра.
ClassName.class нет.

Следовательно, synchronized(this) позволит нескольким экземплярам запускаться одновременно.

Ответ 3

Ключевое слово synchronized при применении к блокировке class в классе и при применении к this блокирует текущий экземпляр объекта. Из спецификации языка Java, раздел 8.4.3.6, "synchronized Methods" :

Синхронизированный метод получает монитор (§17.1) перед его выполнением. Для класса (статического) метода используется монитор, связанный с объектом класса для класса метода. Для метода экземпляра используется связанный с ним монитор (объект, для которого был вызван метод).

Ответ 4

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

  • synchronized(this) получает блокировку экземпляра this для текущего потока. Метод может выполняться параллельно в разных экземплярах (разные значения для этого и, следовательно, разных блокировок)

  • synchronized(SomeClass.class) получает блокировку объекта глобального класса SomeClass. Только один экземпляр метода может работать, поскольку все экземпляры объектов блокируются на одном и том же глобальном объекте (тот же замок).

Ответ 5

Это два разных объекта для блокировки: 'this' относятся к текущему контексту экземпляра, поэтому создание нескольких экземпляров не будет иметь никакого эффекта, если, например, каждый поток использует другой экземпляр и блокирует его. 'this' можно передавать только в нестационарном контексте. "класс" является статическим членом класса Java, и есть только один его экземпляр. Вы можете заблокировать его как в статическом, так и в нестационарном контексте.

Ответ 6

synchronized(this) синхронизирует экземпляр объекта.

synchronized(SomeClass.class) использует экземпляр объекта Class, который представляет SomeClass, который является глобальным для всех экземпляров одного и того же загрузчика классов.

Таким образом, это разные конструкции с различной семантикой.

Используя только synchronized или как модификатор метода, также синхронизируется на семафоре экземпляра, который обычно используется для предотвращения конкуренции между несколькими потоками, обращающимися к этому экземпляру в качестве общего ресурса (то есть списка).

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

class MySharedResourceClass {

    private SomeClass lock = new SomeClass();

    public doSomething() {
        synchronized (lock) {
            // Do something here
        }
    }
}