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

В чем разница между синхронизированным методом и синхронизированным блоком в Java?

В чем разница между синхронизированным методом и синхронизированным блоком в Java?

Я искал ответ в Сети, люди, похоже, так неуверены в этом: - (

Мой ответ будет между ними не будет различий, за исключением того, что блок синхронизации может быть более локализован в области видимости и, следовательно, блокировка будет меньше времени

А в случае Lock на статическом методе, на чем сделан Lock? В чем смысл блокировки по классу?

4b9b3361

Ответ 1

Синхронизированный метод использует приемник метода как блокировку (т.е. this для нестатических методов и класс включения для статических методов). Блок Synchronized использует выражение как блокировку.

Таким образом, следующие два метода эквивалентны для блокировки:

synchronized void mymethod() { ... }

void mymethod() {
  synchronized (this) { ... }
}

Для статических методов класс будет заблокирован:

class MyClass {
  synchronized static mystatic() { ... }

  static mystaticeq() {
    syncrhonized (MyClass.class) { ... }
  }
}

Для синхронизированных блоков вы можете использовать любой объект null как блокировку:

synchronized (mymap) {
  mymap.put(..., ...);
}

Область блокировки

Для синхронизированных методов блокировка будет храниться в пределах области метода, а в блоке Synchronized блокировка сохраняется только во время этой области (иначе называемой критической секцией). На практике JVM разрешается оптимизировать, удаляя некоторые операции из выполнения блока Synchronized, если это может доказать, что это можно сделать безопасно.

Ответ 2

Синхронизированный метод является сокращенным. Это:

class Something {
    public synchronized void doSomething() {
        ...
    }

    public static synchronized void doSomethingStatic() {
        ...
    }
}

для всех целей и целей эквивалентен этому:

class Something {
    public void doSomething() {
        synchronized(this) {
            ...
        }
    }

    public static void doSomethingStatic() {
        synchronized(Something.class) {
            ...
        }
    }
}

(Где Something.class - объект класса для класса Something.)

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

Ответ 3

Да, это одно отличие. Другое дело, что вы можете получить блокировку для других объектов, чем this.

Ответ 4

Ключевое различие заключается в следующем: если вы объявляете метод для синхронизации, то весь массив метода синхронизируется; однако, если вы используете синхронизированный блок, тогда вы можете окружать только "критический раздел" метода в синхронизированном блоке, оставив остальную часть метода вне блока.

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

Ответ 5

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

Где в качестве синхронизированного блока можно заблокировать ЛЮБОЙ объект - обычно объект-мутекс, определенный как переменная экземпляра. Это позволяет больше контролировать, какие блокировки работают.

Ответ 6

Мой ответ будет между ними не будет различий, за исключением того, что блок синхронизации может быть более локализован в области видимости и, следовательно, блокировка будет меньше времени

Да. Ты прав. В отличие от методов synchronized, синхронизированные операторы должны указывать объект, который обеспечивает внутреннюю блокировку.

Пример из учебника java:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

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

Предположим, например, что класс MsLunch имеет два поля экземпляра c1 и c2, которые никогда не используются вместе. Все обновления этих полей должны быть synchronized, но нет никаких оснований препятствовать тому, чтобы обновление c1 было чередованием с обновлением c2 - и это уменьшает concurrency, создавая ненужную блокировку. Вместо использования синхронизированных методов или иным образом с помощью связанного с этим блокировки мы создаем два объекта исключительно для обеспечения блокировок.

А в случае Lock на статическом методе, на чем сделан Lock? В чем смысл блокировки по классу?

В этом случае поток получает внутреннюю блокировку для объекта Class, связанного с классом. Таким образом, доступ к статическим полям класса контролируется блокировкой, отличной от блокировки для любого экземпляра класса.

Когда вы создаете метод synchronized (не static):

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

Если вы создаете метод как static synchronized:

Невозможно чередование двух вызовов методов static synchronized на разных объектах одного и того же класса. Когда один поток выполняет метод static synchronized для объекта класса A, все остальные потоки, которые вызывают методы static synchronized для любого из объектов блока класса А (приостанавливают выполнение) до тех пор, пока первый поток не будет выполнен с выполнением метода.

Вы найдете лучшие альтернативы синхронизации в этом вопросе SE:

Избежать синхронизировать (это) в Java?