В Java критические разделы, на чем я должен синхронизироваться?

Вы могли бы измерить время регистрации, которое не нужно было заполнять вечность текстовыми полями!

70
задан shsteimer 6 January 2009 в 14:47
поделиться

8 ответов

Во-первых, обратите внимание, что следующие фрагменты кода идентичны.

public void foo() {
    synchronized (this) {
        // do something thread-safe
    }
}

и:

public synchronized void foo() {
    // do something thread-safe
}

делают точно то же самое . Никакое предпочтение любого из них за исключением удобочитаемости кода и стиля.

при синхронизации методов или блоков кода важно знать , почему Вы делаете такую вещь, и , какой объект точно Вы блокируете, и для [1 116] что цель .

Также примечание, что существуют ситуации, в которых Вы захотите к клиентский, синхронизируются блоки кода, в которых монитор Вы просите (т.е. синхронизируемый объект) не обязательно this, как в этом примере:

Vector v = getSomeGlobalVector();
synchronized (v) {
    // some thread-safe operation on the vector
}

я предлагаю, чтобы Вы получили больше знания о параллельном программировании, оно будет служить Вам много, как только Вы знаете точно, что происходит негласно. Необходимо проверить Параллельное Программирование в Java, замечательной книге по предмету. Если Вы хотите быстрое погружение - в к предмету, проверяете Параллелизм Java Sun

46
ответ дан Yuval Adam 7 November 2019 в 09:15
поделиться

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

public class Foo {
    private final Object syncObject = new Object();
    …
}

Теперь я могу использовать тот объект для синхронизации без страха перед кем-либо “stealing” блокировка.

39
ответ дан Bombe 7 November 2019 в 09:15
поделиться

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

А особенно ужасный случай возникает, тем не менее, если Вы принимаете решение синхронизироваться на java.lang.String. Строки могут быть (и на практике почти всегда), интернированный. Это означает, что каждая строка равного содержания - в ВЕСЬ JVM - оказывается той же строкой негласно. Это означает, что, если Вы синхронизируетесь на какой-либо Строке, другая (абсолютно разрозненная) секция кода, которая также соединяет Строку с тем же содержанием, на самом деле заблокирует Ваш код также.

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

65
ответ дан Jared 7 November 2019 в 09:15
поделиться

Только для выделения этого существуют также ReadWriteLocks, доступные в Java, найденном как java.util.concurrent.locks. ReadWriteLock.

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

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

Поэтому блокировка чтения-записи имеет больше смысла мне во время многопоточного программирования.

6
ответ дан Kent Lai 7 November 2019 в 09:15
поделиться

Вы захотите синхронизироваться на объекте, который может служить Взаимным исключением. Если текущий экземпляр ( этот ссылка) подходит (не Singleton, например), можно использовать его, как в Java любой Объект может служить Взаимным исключением.

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

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

4
ответ дан Electric Monk 7 November 2019 в 09:15
поделиться

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

Используя другую ссылку специально для блокировки, путем объявления и инициализации частного поля Object lock = new Object(), например, что-то, в чем я никогда не нуждался или использовал. Я думаю, что только полезно при необходимости во внешней синхронизации на двух или больше несинхронизируемых ресурсах в объекте хотя я всегда пытался бы осуществить рефакторинг такую ситуацию в более простую форму.

Так или иначе, неявный (синхронизированный метод) или явный synchronized(this) используется много, также в библиотеках Java. Это - хорошая идиома и, если применимо, должно всегда быть Вашим предпочтительным вариантом.

2
ответ дан eljenso 7 November 2019 в 09:15
поделиться

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

В бывшем случае, с помощью this позволяет нескольким методам быть вызванными атомарным способом. Одним примером является PrintWriter, где можно хотеть произвести несколько строк (скажите отслеживание стека консоли/регистратору), и гарантируйте, что они появляются вместе - в этом случае то, что это скрывается, синхронизирующий объект внутренне является реальной болью. Другим таким примером являются синхронизируемые обертки набора - там необходимо синхронизироваться на самом объекте коллекции для итерации; так как повторение состоит из нескольких вызовов метода, Вы не можете защищать его полностью внутренне.

В последнем случае, я использую простой объект:

private Object mutex=new Object();

Однако видевший много дампов JVM и отслеживаний стека, которые говорят, блокировка является "экземпляром java.lang. Объект ()" я должен сказать, что использование внутреннего класса могло бы часто быть более полезным, как другие предположили.

Так или иначе, это - моя ценность на два бита.

Редактирование: Еще одна вещь, при синхронизации на this я предпочитаю синхронизировать методы и сохранять методы очень детализированными. Я думаю, что это более ясно и более кратко.

4
ответ дан Lawrence Dol 7 November 2019 в 09:15
поделиться

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

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

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

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

1
ответ дан 24 November 2019 в 13:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: