проблема
(1) Позиционирование AQS?
(2) Что является важной частью AQS?
(3) Шаблоны проектирования, используемые AQS?
(4) Общий процесс AQS?
Введение
Полное имя AQS — AbstractQueuedSynchronizer, и его позиционирование — обеспечение базовой структуры почти для всех блокировок и синхронизаторов в Java.
В предыдущих главах мы вместе изучили исходный код ReentrantLock, ReentrantReadWriteLock, Semaphore и CountDownLatch, а сегодня мы вместе подведем итоги AQS.
состояние переменной состояния
В AQS определено состояние переменной состояния, которое можно использовать двумя способами:
(1) Блокировка мьютекса
Когда AQS реализован только как мьютекс, блокировка устанавливается каждый раз, когда значение состояния атомарного обновления изменяется с 0 на 1, а повторный вход достигается путем непрерывного добавления 1 к атомарному обновлению состояния.
(2) Мьютекс + общий замок
Когда AQS необходимо реализовать как блокировку взаимного исключения + общую блокировку одновременно, младшие 16 бит хранят состояние блокировки мьютекса, а старшие 16 бит хранят состояние общей блокировки, которые в основном используются для реализации чтения -запись замков.
Мьютекс — это эксклюзивная блокировка, которая разрешает только один поток за раз, и когда один поток является эксклюзивным, другие потоки больше не смогут получить мьютекс и общую блокировку, но они могут получить саму общую блокировку.
Общая блокировка позволяет одновременно занимать несколько потоков. Пока один поток занимает общую блокировку, все потоки (включая себя) больше не смогут получить блокировку мьютекса, но могут получить общую блокировку.
очередь AQS
В AQS поддерживается очередь. Потоки, которым не удалось получить блокировки (не tryLock()), войдут в очередь и будут ждать освобождения блокировки и пробуждения следующего потока в очереди (в режиме мьютекса).
очередь условий
В AQS есть еще один очень важный внутренний класс ConditionObject, который реализует интерфейс Condition и в основном используется для реализации условных блокировок.
ConditionObject также поддерживает очередь. Эта очередь в основном используется для ожидания установления условия. Когда условие установлено, другие потоки будут сигнализировать элементам в очереди и перемещать их в очередь AQS, ожидая, пока поток удержит блокировку. разблокировать замок быть разбуженным.
Типичным сценарием применения Condition является реализация в BlockingQueue. Когда очередь пуста, поток, который получает элемент, блокируется по условию notEmpty. очередь будет перемещена в AQS Ожидание пробуждения в очереди.
Метод шаблона
Абстрактный класс AQS в совершенстве использует шаблон проектирования метода шаблона, определяя серию методов шаблона, таких как следующие:
// 获取互斥锁
public final void acquire(int arg) {
// tryAcquire(arg)需要子类实现
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// 获取互斥锁可中断
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// tryAcquire(arg)需要子类实现
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
// 获取共享锁
public final void acquireShared(int arg) {
// tryAcquireShared(arg)需要子类实现
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
// 获取共享锁可中断
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// tryAcquireShared(arg)需要子类实现
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
// 释放互斥锁
public final boolean release(int arg) {
// tryRelease(arg)需要子类实现
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
// 释放共享锁
public final boolean releaseShared(int arg) {
// tryReleaseShared(arg)需要子类实现
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
Эти методы получения и снятия блокировок в основном перемежаются при анализе исходного кода ReentrantLock, ReentrantReadWriteLock, Semaphore и CountDownLatch. Теперь удобнее посмотреть, удобнее ли они. Если вы посмотрите на эти исходные коды в начале, вы неизбежно почувствуете головокружение.
Методы, которые должны быть реализованы подклассами
Мы вместе изучили несколько важных шаблонных методов в AQS. Давайте изучим следующие несколько методов, которые должны быть реализованы подклассами:
// 互斥模式下使用:尝试获取锁
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
// 互斥模式下使用:尝试释放锁
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
// 共享模式下使用:尝试获取锁
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
// 共享模式下使用:尝试释放锁
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
// 如果当前线程独占着锁,返回true
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
Почему эти методы не определены напрямую как абстрактные методы?
Поскольку подклассы могут реализовать синхронизатор, если они реализуют некоторые из этих методов, их не нужно определять как абстрактные методы.
Суммировать
Сегодня мы поговорили о нескольких важных частях AQS, и разобрались в этих структурах.У AQS не будет от вас никаких секретов.Конечно, если вы сможете четко ответить на эти пункты во время интервью, у интервьюера тоже будут ясные глаза.
(1) Состояние переменной состояния;
(2) очередь AQS;
(3) очередь условий;
(4) Шаблонный метод;
(5) методы, которые должны быть реализованы подклассами;
пасхальные яйца
После предыдущего исследования не могли бы вы кратко описать общий процесс получения AQS мьютекса?
Брат Тонг здесь не ответит.Я считаю,что после изучения предыдущего содержания,ответить на этот вопрос не проблема.Если вы не можете на него ответить,нужно прочитать рекомендацию ниже и прочитать несколько раз^^
Рекомендуемое чтение
1,Открытие серии java-синхронизации мертвых приседаний
2,Небезопасный анализ мертвого магического класса Java
3.JMM (модель памяти Java) из мертвой серии синхронизации Java
4.Неустойчивый анализ мертвой серии синхронизации Java
5.Синхронный анализ мертвой серии синхронизации Java
6.Напишите блокировку самостоятельно в серии «Синхронизация Java»
7.Начало AQ в серии синхронизации Java
9,ReentrantLock Анализ исходного кода мертвой серии синхронизации Java (2) — условная блокировка
10.ReentrantLock VS синхронизирован в серии синхронизации java
11.Анализ исходного кода ReentrantReadWriteLock мертвой серии синхронизации Java
12.Анализ исходного кода семафора серии Dead Java Synchronization
13,Анализ исходного кода CountDownLatch серии Dead Java Synchronization
Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись «Брат Тонг читает исходный код», просмотреть больше статей в серии исходного кода и поплавать в океане исходного кода с братом Тонгом.