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

Между чем различие synchronized методы и synchronized операторы?

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

8
задан Paŭlo Ebermann 31 August 2011 в 12:22
поделиться

5 ответов

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

Синхронизированные блоки предпочтительнее, если они не эквивалентны всей области действия метода и / или если они блокируют что-то менее драконовское, чем экземпляр (или класс, если он статичен).

13
ответ дан 3 November 2019 в 13:35
поделиться

Цитаты из JLS (включая пример):

JLS 14.19 синхронизированный оператор

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

JLS 8.4.3.6 синхронизированные методы

Метод synchronized получает монитор перед выполнением. Для метода класса ( static ) используется монитор, связанный с объектом Class для класса метода. Для метода экземпляра используется монитор, связанный с this (объектом, для которого был вызван метод).

Это те же самые блокировки, которые могут использоваться оператором synchronized ; таким образом, код:

 class Test {
int count; 
синхронизированный void bump () {count ++; } 
static int classCount; 
static synchronized void classBump () {
classCount ++; 
} 
} 
 

имеет точно такой же эффект, как:

 class BumpTest {
int count; 
void bump () {
synchronized (this) {
count ++; {{1 }}} 
} 
static int classCount; 
static void classBump () {
попробуйте {
синхронизировано (Class.forName ("BumpTest" )) {
classCount ++; 
} 
} catch (ClassNotFoundException e) {
 ... 
} 
} {{ 1}}} 
 

Так чем они отличаются?

Цитаты из Эффективная Java 2-я редакция , пункт 67: Избегайте чрезмерной синхронизации:

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

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

Если ваш метод не очень прост и / или вам необходимо получить блокировку this на весь срок действия метода (или блокировку объекта Class , если метод ] static ) следует использовать операторы synchronized , чтобы ограничить синхронизацию внутри метода только тогда, когда она вам нужна (например, когда вы обращаетесь к совместно используемым изменяемым данным).

8
ответ дан 3 November 2019 в 13:35
поделиться

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

2
ответ дан 3 November 2019 в 13:35
поделиться

Метод synchronized — это метод, тело которого автоматически инкапсулируется в блок synchronized.

Таким образом, это равно:

public void foo()
{
    synchronized (this)
    {
        bar();
    }
}

public synchronized void foo()
{
    bar();
}
4
ответ дан 3 November 2019 в 13:35
поделиться

synchronized на метод заблокирован на объекте this. Он равен синхронизирован (этот) {}

Стандартный synchronized заблокирован на указанном объекте/мониторе. С помощью synchronized (***) {} вы можете выбрать объект для блокировки.

3
ответ дан 3 November 2019 в 13:35
поделиться