Синхронизация метода

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

5 ответов

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

здесь больше информации о мониторах: http://en.wikipedia.org/wiki/Monitor_(synchronization)


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

  • Выходной поток освобождает свою блокировку.

  • Блокировка сообщает планировщику потоков, что он был выпущен.

  • Планировщик потоков изменяет состояние потоков, ожидающих этой блокировки, на "запуск".

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

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


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

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

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

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

Javaword article Bill Venners недвусмысленно объясняет, что на самом деле происходит под капюшонами.

Два кода операций monitorenter и monitorexit используются для блоков синхронизации

Когда monitorenter встречается с помощью Java virtual machine, он получает блокировку для объекта, на который ссылается objectref в стеке. Если нить уже владеет блокировкой для этого объекта, счет увеличивается.

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

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

Посмотрите на связанные вопросы SE:

Что означает "синхронизированный" ?

Как работает синхронизация в Java?


Если это нестатический метод, то это эквивалентная синхронизация по this:

public synchronized void xyz() { ... }

эквивалентно

public void xyz() {
 synchronized(this) {
 ...
 }
}

Если это статический метод, тогда он синхронизируется над объектом класса.


Когда поток A входит в синхронизированный метод, он получает LOCK объекта, вызывающего метод, поэтому любой другой поток не может вызвать синхронизированный метод с использованием этого конкретного объекта. Однако любой поток B может вызывать этот синхронизированный метод, используя какой-либо другой объект того же класса.

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

В то же время, если Thread B и Thread C вызывают один и тот же синхринизированный метод с использованием одного и того же предыдущего объекта, тогда они начнут ждать, пока Thread A освободит Lock on Object. Когда Thread A освободит Lock на объекте, тогда Thread B или Thread C может начать выполнение, Нет гарантии, по которой каждый будет идти первым. Другой будет продолжать ждать.

licensed under cc by-sa 3.0 with attribution.