предисловие
Synchronized — это острое преимущество для решения проблемы доступа к синхронизации данных в параллельных ситуациях. Итак, каков основной принцип синхронизации? Далее давайте очистим его сердцевину слой за слоем, как чистим луковицу, и посмотрим, что получится.
Синхронизированные сценарии использования
Ключевое слово synchronized может воздействовать на методы или блоки кода, и наиболее важными способами являются следующие, как показано на рисунке:
Далее, давайте отделим первый слой от синхронизированного и декомпилируем блоки кода и методы, на которые он воздействует..
синхронизированные действия над кодовыми блоками
public class SynchronizedTest {
public void doSth(){
synchronized (SynchronizedTest.class){
System.out.println("test Synchronized" );
}
}
}
Декомпилируя, вы можете получить:
Как видно из рисунка, добавлен блок кода с ключевым словом synchronized и еще две инструкциимониторвход, мониторвыход. То есть JVM использует monitorenter и monitorexit для достижения синхронизации.Как monitorenter и monitorexit обеспечивают синхронизацию? Мы продолжим исследовать после снятия второго слоя.
синхронизированные действия над методами
public synchronized void doSth(){
System.out.println("test Synchronized method" );
}
Декомпилируя, вы можете получить:
Как видно из рисунка, способ добавления ключевого слова synchronized существует ещеACC_SYNCHRONIZEDотметка. То есть JVM реализует функцию синхронизации, добавляя ACC_SYNCHRONIZED к идентификатору доступа к методу (флаги).
мониторэнтер, мониторэкзит, ACC_SYNCHRONIZED
После отделения первого слоя и декомпиляции метода synchronized и блока кода мы уже знаем, что synchronized синхронизируется через monitorenter, monitorexit и ACC_SYNCHRONIZED.Каковы их три функции? Затем снимаем второй слой:
monitorenter
Введение в команду monitorenter
Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:
If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.
If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.
If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.
Гугл переводчик, вот так:
Каждый объект связан сmonitorСвязанный. Монитор заблокирован тогда и только тогда, когда у него есть владелец (принадлежит). Поток, выполняющий команду monitorenter, попытается получить соответствующий монитор следующим образом:
Каждый объект поддерживает счетчик, который записывает, сколько раз он был заблокирован.Когда объект не заблокирован, счетчик равен 0. Когда поток входит в монитор (выполняет инструкцию monitorenter), он устанавливает счетчик на 1.
Когда тот же поток снова получает блокировку объекта, счетчик снова увеличивается.
Когда другие потоки хотят получить монитор, они будут блокироваться до тех пор, пока счетчик не станет равным 0.
Взгляните на следующую схему для легкого понимания:
monitorexit
Monitorexit Инструкции Введение
The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.
The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.
Гугл переводчик, вот так:
Поток-владелец монитора может выполнить команду monitorexit.
Когда поток выполняет команду monitorexit, счетчик монитора уменьшается на единицу. Если счетчик равен 0, поток больше не владеет монитором. Другим потокам разрешено пытаться получить монитор.
Взгляните на следующую схему для легкого понимания:
ACC_SYNCHRONIZED
Синхронизация на уровне метода выполняется неявно, как часть вызова и возврата метода.Синхронизированный метод выделяется в структуре method_info пула констант времени выполнения флагом ACC_SYNCHRONIZED, который проверяется инструкциями вызова метода.При вызове метода, для которого ACC_SYNCHRONIZED установлен, исполняемый поток входит в монитор, вызывает сам метод и выходит из монитора независимо от того, завершается ли вызов метода нормально или внезапно. Пока исполняющий поток владеет монитором, никакой другой поток не может войти в него. Если возникает исключение выдается во время вызова синхронизированного метода, а синхронизированный метод не обрабатывает исключение, монитор для этого метода автоматически закрывается до повторного создания исключения из синхронизированного метода.
Гугл переводчик, вот так:
Синхронизация уровня метода является неявной, как часть вызова метода. В константном пуле метода синхронизации будет флаг ACC_SYNCHRONIZED.
При вызове метода с установленным флагом ACC_SYNCHRONIZED исполняемый поток должен сначала получить блокировку монитора, а затем начать выполнение метода.После выполнения метода блокировка монитора снимается.Когда метод возвращается нормально или выдает исключение, соответствующая блокировка монитора будет снята.
В течение этого периода, если другие потоки запрашивают выполнение метода, они будут заблокированы, поскольку блокировка монитора не может быть получена.
Если во время выполнения метода возникает исключение, которое не обрабатывается внутри метода, блокировка монитора автоматически снимается до того, как исключение будет выброшено за пределы метода.
Взгляните на эту блок-схему:
Резюме второго уровня Synchronized
- Блок кода синхронизации реализован с помощью monitorenter и monitorexit.Когда поток выполняется для monitorenter, он должен сначала получить блокировку монитора, прежде чем выполнять следующие методы. Когда поток выполняется для мониторинга выхода, блокировка снимается.
- Метод синхронизации реализуется установкой флага ACC_SYNCHRONIZED, когда поток выполняет метод с флагом ACC_SYNCHRONI, ему необходимо получить блокировку монитора.
- Каждый объект поддерживает счетчик блокировок. Если он равен 0, это означает, что блокировку могут получить другие потоки. Если он не равен 0, только поток текущей блокировки может снова получить блокировку.
- Нижний уровень синхронизированных методов и синхронизированных блоков кода синхронизируется через мониторы.
- Каждый объект связан с монитором, и потоки могут владеть монитором или освобождать его.
Ладно, пилинг здесь, у нас еще есть непонятные места,Что такое монитор и почему он может добиться синхронизации? Как объект связан с монитором?как насчет? Не теряйте терпение, мы продолжаем снимать слой, пожалуйста, смотрите вниз.
монитор монитор
Что такое монитор?Затем мы отделяем третий слой Synchronized, что такое монитор?Его можно понимать какИнструмент синхронизации, илимеханизм синхронизации, который обычно описывается как объект. Операционная системамониторявляется концептуальным принципом,ObjectMonitorявляется его принципиальной реализацией.
монитор операционной системы
- Монитор (англ. Monitors, также известный как монитор) — это программная структура, в которой несколько рабочих потоков, образованных несколькими подпрограммами (объектами или модулями) внутри структуры, имеют взаимоисключающий доступ к общим ресурсам.
- Эти общие ресурсы обычно представляют собой аппаратные устройства или группу переменных. Монитор реализует, что не более одного потока выполняет подпрограмму монитора в определенный момент времени.
- Реализации мониторинга значительно упрощают программирование по сравнению с параллельным программированием, где взаимоисключающий доступ достигается путем изменения структур данных.
- Монитор предоставляет механизм, с помощью которого поток может временно отказаться от своего доступа к мьютексу, дождаться выполнения определенных условий, а затем восстановить право выполнения для восстановления своего доступа к мьютексу.
ObjectMonitor
Структура данных ObjectMonitor
В виртуальной машине Java (HotSpot) монитор реализован ObjectMonitor, и его основная структура данных выглядит следующим образом:
ObjectMonitor() {
_header = NULL;
_count = 0; // 记录个数
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL;
_WaitSet = NULL; // 处于wait状态的线程,会被加入到_WaitSet
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ; // 处于等待锁block状态的线程,会被加入到该列表
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
Ключевое слово ObjectMonitor
Значения нескольких ключевых полей в ObjectMonitor показаны на рисунке:
Рабочий механизм
Рабочий механизм Java Monitor показан на рисунке:
- Чтобы получить поток монитора, он сначала войдет в очередь _EntryList.
- Когда поток получает монитор объекта, он входит в область _Owner, устанавливает его как текущий поток и увеличивает счетчик _count на 1.
- Если поток вызывает метод wait(), он войдет в очередь _WaitSet. Он снимет блокировку монитора, то есть присвоит _owner значение null, уменьшит _count на 1 и войдет в очередь _WaitSet для блокировки и ожидания.
- Если другой поток вызывает notify() / notifyAll() , он разбудит поток в _WaitSet, поток снова попытается получить блокировку монитора и в случае успеха войдет в область _Owner.
- После выполнения метода синхронизации поток выходит из критической секции, владелец монитора становится нулевым, а блокировка монитора снимается.
Чтобы было нагляднее, вот пример:
synchronized(this){ //进入_EntryList队列
doSth();
this.wait(); //进入_WaitSet队列
}
Хорошо, мы снимаем еще один слой и знаем, что такое монитор, тогдаКак объект связан с монитором?Шерстяная ткань? Дамы и господа, давайте посмотрим вниз и снимем слой.
Объект связан с монитором
Как объект связан с монитором? Просто сначала посмотрите на картинку:
После прочтения приведенной выше картинки, собственно, у нас есть общее представление о том, как объект связан с монитором.Далее разделимМакет памяти объекта, заголовок объекта, MarkWordПродолжайте исследовать слой за слоем.
Структура памяти объекта
В виртуальной машине HotSpot расположение объектов, хранящихся в памяти, можно разделить на три области: заголовок объекта (Header), данные экземпляра (Instance Data) и заполнение объекта (Padding).
- данные экземпляра: эффективная информация, фактически хранимая объектом, в котором хранится информация об атрибутах класса, включая информацию об атрибутах родительского класса;
- Выровнять отступы: из-за требований виртуальной машины начальный адрес объекта должен быть целым числом, кратным 8 байтам. Данные заполнения не требуются, они нужны только для выравнивания байтов.
- заголовок объекта: Заголовок объекта виртуальной машины Hotspot в основном включает две части данных: Mark Word (поле метки) и Class Pointer (указатель типа).
заголовок объекта
Заголовок объекта в основном включает в себя две части данных: Mark Word (поле отметки), Class Pointer (указатель типа).
- Class Pointer: указатель объекта на его метаданные класса, виртуальная машина использует этот указатель, чтобы определить, экземпляром какого класса является объект.
- Mark Word: используется для хранения данных времени выполнения самого объекта, что является ключом к реализации упрощенных блокировок и блокировок с пристрастием.
Mark word
Mark Word используется для хранения данных времени выполнения самого объекта, таких как хэш-код (HashCode), возраст генерации GC, флаги состояния блокировки, блокировки, удерживаемые потоками, смещенные идентификаторы потоков, смещенные временные метки и т. д.
В 32-битной виртуальной машине HotSpot, если объект находится в разблокированном состоянии, 25 бит в 32-битном пространстве Mark Word используются для хранения хэш-кода объекта, 4 бита используются для хранения возраста создания объекта и 2 бита используются для хранения бита флага блокировки, 1 бит фиксируется на 0, что указывает на беспристрастную блокировку. Другие состояния показаны на следующем рисунке:
- Из предыдущего анализа видно, что для монитора характерно взаимное исключение.Тяжеловесная блокировка, указатель на мьютекс.
- На самом деле синхронизированотяжелый замок, то есть блокировка объекта Synchronized, флаг блокировки Mark Word равен 10, а указатель указывает на начальный адрес объекта Monitor.
- Вдруг вы не чувствуете, что есть еще одна деревня в темной и светлой! Как объект связан с монитором? Отвечать:Пометить блокировку тяжеловесного слова Word, указатель указывает на адрес монитора.
Synchronized отрывает сводку четвертого слоя
Как объекты связаны с мониторами?
- заголовок объекта
- Заголовок объекта с Mark Word в нем
- Указатель Mark Word указывает на монитор
оптимизация блокировки
На самом деле, только до версии JDK1.6 реализация synchronized будет напрямую вызывать вход и выход из ObjectMonitor, такой тип блокировки называется тяжеловесной блокировкой.Тяжелый замок, зачем им так часто пользоваться?Начиная с JDK6, команда разработчиков виртуальных машин HotSpot оптимизировала блокировки в Java, например, добавив такие стратегии оптимизации, как адаптивное вращение, устранение блокировок, огрубление блокировок, облегченные блокировки и блокировки со смещением.
блокировка спина
Что такое спин-блокировка?
Спин-блокировка означает, что когда поток пытается получить блокировку, если блокировка уже занята другими потоками, он продолжает зацикливаться, чтобы определить, снята ли блокировка, вместо того, чтобы переходить в состояние приостановки или сна потока.
Зачем нужен спинлок?
Блокировка и пробуждение потоков требуют переключения ЦП из пользовательского режима в основной режим, а частые блокировки и пробуждения явно тяжелы для ЦП. На самом деле, во многих случаях состояние блокировки длится лишь короткий период времени, и в течение этого короткого периода времени определенно не стоит часто блокировать и пробуждать поток. Так появились спин-блокировки.
Сценарии применения Spinlock
Спин-блокировка подходит для случая, когда критическая область, защищаемая замком, мала.Если критическая область мала, время, занимаемое замком, очень короткое.
Некоторые мысли о спин-блокировках
Здесь я хочу поговорить о том,Почему ConcurrentHashMap отказывается от блокировки сегментов и использует режим вращения CAS, на самом деле это правда.
снятие блокировки
Что такое снятие блокировки?
Снятие блокировки означает, что JIT-компилятор виртуальной машины удаляет блокировки, требующие синхронизации для некоторых кодов, но при этом обнаруживается отсутствие конкуренции за общие данные.
Замки избавляют от некоторого мышления
Здесь я хотел бы расширить ежедневную разработку кода, некоторые разработчики также используют блокировку в отсутствие параллелизма. Если возможности параллелизма нет, перейдите непосредственно к ConcurrentHashMap.
замок огрубление
Что такое блокировка?
Концепция сленга замков проста для понимания: это соединение нескольких последовательных операций блокировки и разблокировки вместе, чтобы расшириться до блокировки с более широким диапазоном.
Зачем нужно блокировать аренду?
При использовании блокировок синхронизации необходимо, чтобы объем синхронизируемого блока был как можно меньше — синхронизируйте только в фактическом объеме общих данных. Цель этого — свести к минимуму количество операций, которые необходимо синхронизировать. является конкуренцией замков, то поток, ожидающий блокировки, может получить блокировку как можно скорее.Однако, если серия непрерывных операций блокировки и разблокировки может привести к ненужной потере производительности, вводится понятие сленга блокировки.
Метафора блокировки мышления об аренде
Например, покупка билета в зоопарк. Воспитатель берет в гости группу детей.Если контролер знает, что это группа, он может рассматривать их как единое целое (фиксированная арендная плата) и проверять билеты одновременно, вместо того, чтобы просить их проверять билеты по одному. .
Суммировать
Давайте просто завершим это синхронизированной луковой диаграммой, если вы готовы чистить мое сердце слой за слоем.
Ссылка и спасибо
- Синхронизированный монитору-у-у. Краткое описание.com/afraid/32 oh 136181…
- Глубокое понимание многопоточности (1) - принцип реализации SynchronizedВуху. Hollisbeds.com/archives/18…
- Глубокое понимание многопоточности (5) - технология оптимизации блокировок виртуальной машины JavaВуху. Hollisbeds.com/archives/23…
- "Глубокое понимание виртуальной машины Java"
Личный публичный аккаунт
Приглашаем всех обратить внимание, учиться и обсуждать вместе.