Spec-Zone .ru
спецификации, руководства, описания, API
|
Синхронизация создается вокруг внутреннего объекта, известного как внутренняя блокировка или блокировка монитора. (Спецификация API часто обращается к этому объекту просто как "монитор."), Внутренние блокировки играют роль в обоих аспектах синхронизации: осуществление эксклюзивного доступа к состоянию объекта и установлению происходит - перед отношениями, которые важны для видимости.
У каждого объекта есть внутренняя блокировка, связанная с этим. Условно, поток, который нуждается в монопольном и непротиворечивом доступе к полям объекта, должен получить внутреннюю блокировку объекта прежде, чем получить доступ к ним, и затем выпустить внутреннюю блокировку, когда это делается с ними. Потоку, как говорят, принадлежит внутренняя блокировка между временем, это получило блокировку и выпустило блокировку. Пока потоку принадлежит внутренняя блокировка, никакой другой поток не может получить ту же самую блокировку. Другой поток блокирует, когда он попытается получить блокировку.
Когда поток выпускает внутреннюю блокировку, происхождение - прежде, чем отношение будет установлено между тем действием и любым последующим acquistion той же самой блокировки.
Когда поток вызывает синхронизируемый метод, он автоматически получает внутреннюю блокировку для объекта того метода и выпускает это, когда метод возвращается. Выпуск блокировки происходит, даже если возврат был вызван непойманным исключением.
Вы могли бы задаться вопросом, что происходит, когда статический синхронизируемый метод вызывается, так как статический метод связывается с class, не объектом. В этом случае поток получает внутреннюю блокировку для Class
объект связался с class. Таким образом доступом к статическим полям class управляет блокировка, это отлично от блокировки для любого экземпляра class.
Другой способ создать синхронизируемый код с синхронизируемыми операторами. В отличие от синхронизируемых методов, синхронизируемые операторы должны определить объект, который обеспечивает внутреннюю блокировку:
public void addName(String name) { synchronized(this) { lastName = name; nameCount++; } nameList.add(name); }
В этом примере, addName
метод должен синхронизировать изменения с lastName
и nameCount
, но также и потребности избежать синхронизировать вызовы методов других объектов. (Вызов методов других объектов от синхронизируемого кода может создать проблемы, которые описываются в разделе по Живому.) Без синхронизируемых операторов, должен был бы быть отдельный, несинхронизируемый метод в единственной цели вызвать nameList.add
.
Синхронизируемые операторы также полезны для улучшения параллелизма с мелкомодульной синхронизацией. Предположите, например, class MsLunch
имеет два поля экземпляра, c1
и c2
, это никогда не используется вместе. Все обновления этих полей должны синхронизироваться, но нет никакой причины препятствовать тому, чтобы обновление c1 было чередовано с обновлением c2 — и делать так уменьшает параллелизм, создавая ненужное блокирование. Вместо того, чтобы использовать синхронизируемые методы или иначе использовать блокировку, связанную с this
, мы создаем два объекта исключительно, чтобы обеспечить блокировки.
public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } }
Используйте эту идиому с большой осторожностью. Следует быть абсолютно уверены, что действительно безопасно чередовать доступ полей, на которые влияют.
Вспомните, что поток не может получить блокировку, принадлежавшую другому потоку. Но поток может получить блокировку, которую он уже имеет. Разрешение потока получить ту же самую блокировку не раз включает повторно используемой синхронизации. Это описывает ситуацию, где синхронизируемый код, прямо или косвенно, вызывает метод, который также содержит синхронизируемый код, и оба набора кода используют ту же самую блокировку. Без повторно используемой синхронизации синхронизируемый код должен был бы взять много дополнительных предосторожностей, чтобы избежать иметь причину потока непосредственно, чтобы блокировать.