Между чем различие synchronized
методы и synchronized
операторы?
Если возможно, используйте пример для создания этого более ясным.
Синхронизированный метод блокирует монитор, связанный с экземпляром класса (т. Е. «Это») или классом (если статический метод), и предотвращает доступ других так до возврата из метода. Синхронизированный блок может заблокировать любой монитор (вы указываете ему какой) и может иметь меньшую область видимости, чем у метода включения.
Синхронизированные блоки предпочтительнее, если они не эквивалентны всей области действия метода и / или если они блокируют что-то менее драконовское, чем экземпляр (или класс, если он статичен).
Цитаты из JLS (включая пример):
синхронизированный
оператор A
синхронизированный
оператор получает блокировку взаимного исключения от имени исполняемого потока, выполняет блок, а затем снимает блокировку. Пока исполняющий поток владеет блокировкой, никакой другой поток не может получить блокировку.
синхронизированные
методы Метод
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
, чтобы ограничить синхронизацию внутри метода только тогда, когда она вам нужна (например, когда вы обращаетесь к совместно используемым изменяемым данным).
Синхронизированный метод - это метод, в котором вы фактически поместили все тело функции в синхронизированный блок. Преимущество синхронизированного блока состоит в том, что вы можете применить синхронизированный блок только к нескольким операторам выбора в функции, а не к функции в целом. В общем, лучше всего делать синхронизированные блоки как можно короче, поскольку время, проведенное в синхронизированных блоках, - это время, когда какой-либо другой поток может не выполнять значимую работу. Другое отличие состоит в том, что вы можете указать конкретный объект, к которому следует применить блокировку, при использовании синхронизированного блока, тогда как в синхронизированном методе сам объект автоматически используется в качестве блокировки, для которой выполняется синхронизация.
Метод synchronized
— это метод, тело которого автоматически инкапсулируется в блок synchronized
.
Таким образом, это равно:
public void foo()
{
synchronized (this)
{
bar();
}
}
public synchronized void foo()
{
bar();
}
synchronized
на метод заблокирован на объекте this
. Он равен синхронизирован (этот) {}
Стандартный synchronized
заблокирован на указанном объекте/мониторе. С помощью synchronized (***) {}
вы можете выбрать объект для блокировки.