Слияние кода завершено, страница обновится автоматически
Пессимистический блокировщик: synchronized
#Synchronized блокировщик является пессимистическим блокировщиком, у него есть явный недостаток: он блокирует данные независимо от того, существует ли конкуренция или нет. С увеличением количества параллельных запросов и увеличением времени блокировки, производительность значительно снижается.
#Каждый объект содержит две части: одна часть содержит собственные данные выполнения, такие как хэш-код (HashCode), возраст поколения сборки мусора (GC), флаг состояния блокировки, удерживаемые объектом блокировки, идентификатор блокировки предпочтения, метку времени предпочтения и т. д. Вторая часть содержит указатель типа, который указывает на метаданные типа объекта.
#Блокировка объекта (monitor) находится в заголовке объекта. Инструкция MonitorEnter вставляется в начале блока синхронизации, когда код выполняется до этой инструкции, он пытается получить владение объектом Monitor, то есть пытается получить блокировку объекта. Инструкция MonitorExit вставляется в конце метода и в блоках исключений, JVM гарантирует, что каждая инструкция MonitorEnter имеет соответствующую инструкцию MonitorExit.
#Другие потоки, которые хотят получить эту блокировку, должны быть заблокированы. Переключение между состояниями пользователя и ядра для выполнения этих операций очень дорого, так как это требует переключения контекста процессора. #Характеристики: мьютекс, неравнодушный блокировщик, рекурсивный, не прерываемый.
#Преимущества: простая реализация.
#Недостатки:
#Блокировка независимо от того, существует ли конкуренция или нет, что приводит к снижению производительности при увеличении количества параллельных запросов и увеличении времени блокировки.
#Не прерываемый, что означает, что synchronized не может помочь прервать задачу в случае ожидания.
#Мьютекс переходит в состояние сна или блокировки при неудачной попытке получить блокировку.Оптимистический блокировщик: CAS (compare and swap, сравнение и замена)
#Спин-блокировка
#Пессимистический блокировщик блокирует весь объект перед выполнением операции, в то время как оптимистический блокировщик не блокирует объект и сразу выполняет операцию, а затем проверяет, нужно ли обновлять данные.
#Основной алгоритм оптимистического блокировщика — это CAS (Compare and Swap, сравнение и замена), который включает три операнда: значение в памяти, ожидаемое значение и новое значение. Значение в памяти заменяется новым значением только в том случае, если ожидаемое значение совпадает со значением в памяти.
#Логика обработки заключается в том, чтобы сначала проверить, совпадает ли значение определенного участка памяти с тем, которое было прочитано ранее. Если значение не совпадает, это означает, что значение было изменено другим потоком, и текущая операция отменяется. Если значение совпадает, это означает, что значение не было изменено другим потоком, и новое значение может быть установлено для этого участка памяти.
#Преимущества: высокая производительность при параллельных запросах, JDK использует оптимистический блокировщик на основе CAS в своих пакетах параллелизма.
#Недостатки:
#Оптимистический блокировщик гарантирует атомарную операцию только для одного общего переменной.
#Долгое вращение может привести к большим затратам.
#Проблема ABA.Основная идея CAS (Compare and Swap) заключается в сравнении значения в памяти с ожидаемым значением для определения, было ли значение в памяти изменено. Однако этот логический подход не является строго корректным: если значение в памяти изначально было A, затем было изменено на B одним из потоков, а затем снова на A, то CAS считает, что значение в памяти не было изменено. Однако на самом деле оно было изменено другими потоками, что может существенно повлиять на результаты вычислений, которые зависят от промежуточных значений.Решение заключается в использовании версионного номера, который увеличивается каждый раз при обновлении переменной.**Синхронизатор: AQS (AbstractQueuedSynchronizer)**
- **Определение:** Он предоставляет базовую структуру для реализации блокировок и синхронизации для различных сценариев, обеспечивая атомарное управление состоянием, блокировку и разблокировку потоков, а также управление очередями.
- **Принцип:** AQS упаковывает потоки в узлы и поддерживает FIFO-очередь из узлов CHL (Condition-Holding-Node). Это неблокирующая FIFO-очередь, то есть в условиях конкурентного доступа операции вставки или удаления узлов не блокируют выполнение. Атомарность вставки и удаления узлов обеспечивается с помощью спин-блокировки и CAS.
- **state**
- **Уникальный режим:** значение state может быть только 0 или 1.
- **Режим совместного использования:** state может быть изменен на любое целое число. Обычно начальное значение представляет ширину канала, через который могут пройти n потоков одновременно. Потоки могут попытаться уменьшить значение state на 1 с помощью метода tryAcquireShared. Если изменение state успешно, поток может продолжить выполнение. После завершения выполнения поток может попытаться увеличить значение state на 1 с помощью метода tryReleaseShared.
- **Уникальный режим:** в отличие от режима совместного использования, где требуется использование метода CAS для изменения state, поскольку несколько потоков могут конкурентно освобождать блокировку. - **Уникальный режим:** канал, который позволяет пройти только одному потоку за раз, создавая эффект мьютекса.
- **Режим совместного использования:** канал с шириной больше 1, который позволяет пройти n потоков одновременно, увеличивая пропускную способность, но может вызывать проблемы с согласованностью данных.**Три способа блокировки и разблокировки:**
- **suspend и resume:** эти методы были отменены в Java из-за неизбежных проблем с расконкуренцией.
- **wait и notify:** эти методы должны использоваться внутри блокировки synchronized, они могут вызывать проблемы с расконкуренцией. wait должен быть вызван до notify, иначе поток может быть заблокирован навсегда.
- **await и signal:** класс Condition предоставляет объект Condition, получаемый с помощью new ReentrantLock(). newCondition(), как и wait и notify. Поскольку после использования Lock нельзя использовать метод wait, используются await и signal.
#wait и await различия:
#wait и notify должны использоваться вместе с synchronized, поскольку перед вызовом необходимо удерживать блокировку, wait немедленно освобождает блокировку, в то время как notify освобождает блокировку только после завершения синхронизированного блока.
#Поскольку Lock не использует механизм synchronized, метод wait не может использоваться для управления многопоточностью, поэтому используется await объекта Condition.
#park и unpark: предоставляются классом LockSupport, а реализация основана на методах Unsafe класса. Поскольку park и unpark используют механизм разрешений, максимальное количество разрешений равно 1, поэтому операции park и unpark не накапливаются, и unpark может быть вызван до park. Если unpark вызывается раньше, park не блокирует поток.#Lock реализация основана на AQS, а реализация AQS основана на LockSupport, поэтому LockSupport является более низким уровнем, и не рекомендуется использовать park и unpark для блокировки и пробуждения потоков.
Внутри Java существует два механизма блокировки: 1. synchronized 2. Lock
Различия:
#Реализация механизма различна
#synchronized подразделяется на два типа: для сегмента программы synchronized реализуется с помощью монитора. enter и монитора. exit, а для методов и классов — с помощью установки блокировочного поля экземпляра или класса.
#Реализация Lock основана на AQS. AQS представляет собой список потоков, который управляет состоянием потоков и их расписанием. AQS также является блокировкой, которая гарантирует, что только один поток может получить блокировку AQS в одно и то же время, то есть только один узел со статусом running (почему не один поток, который работает в одно и то же время? Потому что при запросе блокировки поток сначала добавляется в очередь и затем приостанавливается, а при фейрном конкурентном доступе все потоки пробуждаются).
synchronized: синхронизированный блок# Принцип: у любого объекта есть монитор, связанный с ним. Когда монитор удерживается одним объектом, он находится в состоянии блокировки. Реализация synchronized в JVM основана на входе и выходе из объекта монитора, который обеспечивает синхронизацию методов и блоков кода. Хотя конкретные детали реализации могут различаться, они все могут быть реализованы с помощью пары инструкций MonitorEnter и MonitorExit.## Инструкция MonitorEnter вставляется в начале синхронизированного блока кода, и когда выполнение доходит до этой инструкции, попытка получить владение объектом монитора, то есть попытка получить блокировку объекта. Инструкция MonitorExit вставляется в конце метода и при исключении; JVM гарантирует, что каждая инструкция MonitorEnter имеет соответствующую инструкцию MonitorExit. ## В этом случае, если требуется заблокировать или разбудить поток, требуется помощь операционной системы. Это требует переключения из пользовательского режима в режим ядра для выполнения, что является дорогостоящей операцией, требующей значительного количества времени процессора. Если возможно, следует уменьшить количество таких переключений. JVM обычно применяет оптимизации, такие как вращение потока перед блокировкой, чтобы избежать переключения из пользовательского режима в режим ядра, если блокировка не требуется.## В Java каждый объект может быть использован как блокировка, что является основой для реализации синхронизации с помощью synchronized:
- Обычный синхронизированный метод, блокировка — текущий экземпляр объекта.
- Статический синхронизированный метод, блокировка — объект класса.
- Синхронизированный блок кода, блокировка — объект, указанный в скобках.
## Инструмент javap может быть использован для анализа информации о сгенерированном классе, чтобы понять реализацию synchronized:
- Синхронизированный блок кода: инструкция monitorenter вставляется в начале синхронизированного блока кода, а инструкция monitorexit — в конце. JVM гарантирует, что каждая инструкция monitorenter имеет соответствующую инструкцию monitorexit. Каждый объект имеет связанную с ним монитор, и когда монитор захвачен, он находится в заблокированном состоянии. При выполнении потоком инструкции monitorenter поток пытается получить владение монитором, то есть получить блокировку объекта.
- Синхронизированный метод: синхронизированный метод транслируется в обычные инструкции вызова и возврата, такие как invokevirtual и areturn. На уровне виртуальной машины нет специальных инструкций для реализации синхронизированных методов.Вместо этого в поле access_flags таблицы методов класса файла Class устанавливается флаг synchronized, указывающий на то, что метод является синхронизированным и использует объект или внутренний объект класса Klass в JVM в качестве блокировки.
## Объектные заголовки Java и мониторы являются основой для реализации synchronized.
## Характеристики: мьютекс, несправедливая блокировка, рекурсивная блокировка, не прерываемая, простота использования.
## Высокая производительность и рекомендации: с JDK 6 и далее, при небольшом количестве параллельных операций, производительность средняя и стабильная. Рекомендуется новичкам использовать.Реализация блокировки Lock:
ReentrantLock — рекурсивная блокировка
- Использование: ReentrantLock является реализацией интерфейса Lock. Основные методы интерфейса Lock — lock(), unlock(), tryLock(). Можно использовать Condition для управления потоками, await() похож на object.wait(), signal() похож на object.notify(), signalAll() похож на object.notifyAll(). Принцип: Основной класс AbstractQueuedSynchronizer, который построит блокирующую CLH-очередь для всех блокирующих потоков, а все операции над этой очередью будут выполняться с использованием операций без блокировки (CAS). Однако для потоков, которые уже получили блокировку, ReentrantLock реализует функциональность предпочтительной блокировки.
Характеристики: поддерживает fair-lock, timed-lock, condition-lock, polling-lock, interruptible-lock. Может эффективно избегать ситуации deadlock.
Производительность и рекомендации: средняя производительность, рекомендуется использовать при необходимости ручного управления потоками.
ReentrantReadWriteLock — чтение-запись блокировка
- Использование: Разрешает многим потокам одновременно читать определенный ресурс, но разрешает только одному потоку писать. Основные методы интерфейса ReadWriteLock — это readLock() и writeLock(). Реализует параллельное чтение и взаимоисключение при записи. Однако чтение блокирует запись, что является стратегией пессимистического подхода.
Когда несколько потоков читают переменную, можно использовать чтение блокировку rwl.readLock().lock();, если требуется изменить переменную, можно использовать запись блокировки rwl.writeLock().lock(); //запись блокировка, которая не позволяет другим потокам читать или писать.
# Сравнение с повторяемой блокировкой: принцип реализации одинаков, но чтение-запись блокировка лучше подходит для сценариев с большим количеством чтений и меньшим количеством записей, так как чтения могут быть совместно использованы, в то время как повторяемая блокировка полностью исключает запись.
StampedLock Блокировка на основе временных меток (улучшенная блокировка чтение-запись в jdk1.8)
# Использование: Улучшение записи блокировки, идея заключается в том, что чтение в блокировке чтение-запись не блокирует чтение, а также не должно блокировать запись. Если во время чтения происходит запись, то следует перечитать, а не блокировать запись во время чтения!
# Сравнение с блокировкой чтение-запись: чтение блокировка не блокирует запись блокировку, если временная метка недействительна, то следует перечитать значение переменной. Отсутствует проблема ABA.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )