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

StackOverflow https://stackoverflow.com/questions/1149928

Вопрос

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

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

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

И в случае блокировки статического метода, на что заблокирован? В чем смысл блокировки в классе?

Это было полезно?

Решение

Синхронизированный метод использует приемник метода в качестве блокировки (т.е. 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 Блок выполнение, если это может доказать, что это может быть сделано безопасно.

Другие советы

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

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.)

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

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

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

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

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

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

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

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

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

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

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

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

И в случае блокировки статического метода, на что заблокирован? В чем смысл блокировки в классе?

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

Когда вы делаете метод как синхронизированный (не static ) :

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

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

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

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

Избегайте синхронизации (это) на Java?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top