Чтобы изучить программирование параллелизма Java, мы должны узнать о пакете Java.Util.concurrent. Существует много классов инструментов параллелизма, которые мы часто используем в этом пакете, такие как: reentrantlock, countdownlatch, cyclicbarrier, semaphore и т. Д. Основная реализация этих классов полагается на класс AbstractQueuedSynchronizer, который показывает важность этого класса. Итак, в серии java Antorurrency я впервые проанализировал класс AbstractQueuedSynchronizer. Поскольку этот класс более важен, и код является относительно длинным, чтобы проанализировать его максимально тщательно, я решил использовать четыре статьи, чтобы дать относительно полное введение в этот класс. Эта статья является кратким введением, чтобы дать читателям предварительное понимание этой категории. Для простоты повествования в некоторых местах будут использовать AQ для представления этого класса в будущем.
1. Для чего нужен класс AbstractQueuedSynchronizer?
Я считаю, что многие читатели использовали Reentrantlock, но они не знают существования AbstractQueuedSynchronizer. Фактически, Reentrantlock реализует внутреннюю синхронизацию класса, которая наследует AbstractQueuedSynchronizer. Все реализации механизма блокировки основаны на синхронизации внутренних классов. Можно также сказать, что реализация Reentrantlock зависит от класса AbstractQueuedSynchronizer. Аналогичным образом, Countdownlatch, Cyclicbarrier и Semaphore Class также используют тот же метод для реализации собственного управления блокировками. Можно видеть, что AbstractQueuedSynchronizer является краеугольным камнем этих классов. Так что же реализовано внутри AQS, так что от этого зависят все эти классы? Можно сказать, что AQS предоставляет инфраструктуру для этих классов, то есть он обеспечивает блокировку пароля. После того, как эти классы имеют блокировку пароля, они сами могут установить пароль блокировки пароля. Кроме того, AQS также обеспечивает зону очереди и инструктор по ните. Мы знаем, что темы похожи на примитивный варвар. Они не знают, как быть вежливым. Они будут только спешить, поэтому вы должны научить его шаг за шагом, сказать это, когда ему нужно стоять в очереди, где стоять в очереди, что делать, прежде чем стоять в очереди и что делать после очереди. Все эти образовательные работы завершены AQS для вас. Образованные из него нить стали очень цивилизованными и вежливыми, и больше не являются примитивными варварами. Таким образом, в будущем нам нужно только иметь дело с этими цивилизованными темами. Никогда не слишком много контактов с оригинальными темами!
2. Почему AbstractQueuedSynchronizer предоставляет блокировку пароля?
// Головой узел очереди синхронизации // Хвостовой узел хвоста синхронизации {return uncafe.compareAndswapint (это, AttecleOffSet, ожидайте, обновление);}Приведенный выше код перечисляет все переменные члена AQS. Вы можете видеть, что существует только три переменные элемента AQS, а именно ссылка на узел узла очереди синхронизации, ссылка на хвостовую узлу синхронизации и состояние синхронизации. Обратите внимание, что все три переменные элемента изменяются с помощью нестабильного ключевого слова, что гарантирует, что несколько потоков изменяют его, видимо. Ядром всего класса является это состояние синхронизации. Вы можете видеть, что состояние синхронизации на самом деле является переменной Int-Type. Вы можете рассматривать это состояние синхронизации как блокировку пароля, а также является заблокированным паролем в комнате. Конкретное значение состояния эквивалентно паролю, управляющему открытием и закрытием блокировки пароля. Конечно, пароль этой блокировки определяется каждым подклассом. Например, в повторном отделении состояние равна 0 означает, что блокировка открыта, утверждение больше 0 означает, что блокировка заблокирована, а в семафоре утверждение больше 0 означает, что блокировка открыта, а состояние равна 0 означает, что блокировка заблокирована.
3. Как внедряется область очереди AbstractQueuedSynchronizer?
На самом деле есть две зоны очереди в AbstractQueuedSynchronicizer, одна - синхронная очередь, а другая - условная очередь. Как видно из приведенного выше рисунка, существует только одна очередь синхронизации, в то время как может быть несколько очередей состояния. Узлы синхронной очереди содержат ссылки на передние и задние узлы соответственно, в то время как узлы условной очереди имеют только одну ссылку на узел преемника. На рисунке t представляет собой нить. Каждый узел содержит поток. После того, как поток не может получить блокировку, он сначала входит в очередь синхронизации в очереди. Если вы хотите ввести условную очередь, поток должен удерживать блокировку. Затем давайте посмотрим на структуру каждого узла в очереди.
// узлы синхронной очереди являются статическим окончательным узлом класса {статический окончательный узел areed = new Node (); // текущий поток удерживает блокировку в общем режиме статического окончательного узла exclusive = null; // текущий поток удерживает блокировку в эксклюзивном режиме Static Final int int decpled = 1; // текущий узел отменил статический блокирующий конечный сигнал int = -1; // потоки узла преемника должны запустить статическое окончательное условие int = -2; // текущий узел в очереди в условной очереди статической конечной int propagate = -3; // Последующий узел может напрямую приобрести блокировку viateStatus; // Обозначите состояние ожидания текущего узла летучего узла Prev; // Обозначите прямой узел в летучим узле очереди синхронизации следующим; // Обозначите узел преемника в резьбе по очереди синхронизации. // поток, удерживаемый текущим узлом, относится к Node NextWaiter; // Обозначите узел преемника в условной очереди // является текущим состоянием узла в окончательном логическом режиме общего режима } // Вернуть прямой узел текущего узла окончательного узла предшественника () бросает NullPointerException {node p = prev; if (p == null) {бросить новый nullpointerexception (); } else {return p; }} // Constructor 1 node () {} // Конструктор 2, этот конструктор используется для узла по умолчанию (поток потока, режим узла) {// Обратите внимание, что режим удержания присваивается NextWaiter this.nextwaiter = mode; this.Thread = Thread; } // Constructor 3, только узел (поток потока, int QuaitsTatus) используется в очереди условий {this.waitstatus = witfstatus; this.Thread = Thread; }}Узел представляет узел в очереди синхронизации и условную очередь. Это внутренний класс AbstractQueuedSynchronicrizer. Узел имеет много атрибутов, таких как режим удержания, состояние ожидания, предварительная последовательность и преемник в синхронных очередах, а также ссылки на преемника в условных очереди и т. Д. Стоки синхронизации и очередь состояния можно рассматривать как область очереди, каждый узел рассматривается как место в области докладчики, а поток рассматривается в качестве гостя. Когда гости впервые появятся, они постучат в дверь, чтобы увидеть, открыт ли замок. Если замок не будет открыт, они пойдут в зону очереди, чтобы собрать номерную плиту, заявить, как они хотят удержать замок, и, наконец, в очереди в конце очереди.
4 Как понять эксклюзивный режим и режим обмена?
Как упоминалось ранее, каждый гость получит номерной номер до очередей и заявляет, что хочет обладать замком. Способ владения блокировкой делятся на эксклюзивный режим и режим обмена. Итак, как вы понимаете эксклюзивный режим и режим обмена? Я действительно не могу найти хорошую аналогию. Вы можете подумать о общественном туалете. Люди с эксклюзивным режимом более доминируют. Я либо не захожу. Когда я захожу, я не позволяю другим войти. Я занимаю весь туалет в одиночку. Люди в режиме совместного использования не так конкретны. Когда они обнаруживают, что туалет уже используется, он не учитывается, если он поступает сам по себе. Они также должны с энтузиазмом спросить людей, стоящих за людьми, не возражают ли они, используя это вместе. Если люди позади не возражают, используя его вместе, нет необходимости в очереди. Все пойдут вместе. Конечно, если люди, стоящие за ними, должны оставаться в очереди и продолжать очереди.
5 Как понять состояние ожидания узла?
Мы также видим, что каждый узел имеет состояние ожидания, которое разделено на четыре состояния: отменено, сигнал, состояние и распространение. Это состояние ожидания можно рассматривать как знак, висящий рядом с сиденьем, идентифицируя состояние ожидания человека на текущем месте. Статус этого бренда может быть не только изменен самостоятельно, но и другие также могут его изменить. Например, когда этот поток уже планирует сдаться во время очереди, он установит на его сиденье знак на отмену, чтобы другие могли очистить его из очереди, если они его увидят. Другая ситуация заключается в том, что, когда нить собирается заснуть на сиденье, она боится, что она заснет, поэтому она изменит знак в переднем положении, чтобы сигнализировать, потому что все вернутся на свои места, прежде чем покинуть очередь, чтобы взглянуть. Если он увидит, что статус на знаке является сигналом, он разбудит следующего человека. Только гарантируя, что бренд в переднем положении является сигналом, нынешняя поток будет спать мирно. Состояние условия указывает, что поток в очереди в условной очереди. Статус распространения напоминает последующие потоки, чтобы приобрести блокировку напрямую. Этот статус используется только в общем режиме и будет обсуждаться позже, когда рассказывают об общем режиме отдельно.
6. Какие операции будут выполнены, когда узел входит в очередь синхронизации?
// Операция по энкеуэуэуэуэуэуэру, вернуться к предыдущему узлу под частным узлом ENQ (конечный узл узла) {for (;;) {// Получить ссылку на хвостовой узел узла очереди синхронизации t = хвост; // Если хвостовой узел пуст, это означает, что очередь синхронизации не была инициализирована, если (t == null) {// Инициализируют очередь синхронизации, если (сравнение (new node ())) {tail = head; }} else {// 1. Укажите на текущий узел узла хвостового узла. Prev = t; // 2. Установите текущий узел в хвостовой узел if (CompareandStatail (t, Node)) {// 3. Укажите преемника старого хвостового узла на новый хвостовой узел T.Next = Node; // единственный выход из петли возврата t; }}}}Обратите внимание, что операция Enqueue использует мертвую петлю. Только когда узел успешно добавлен в хвост очереди синхронизации, он будет возвращен. Результатом является исходный хвостовой узел очереди синхронизации. На следующем рисунке показан весь процесс работы.
Читатели должны обратить внимание на порядок добавления хвостовых узлов, которые делятся на три шага: указывая на хвостовые узлы, CAS изменяют узлы хвоста и указывают на преемников старого хвостового узла на текущий узел. В одновременной среде эти три шага не могут быть завершены. Следовательно, при операции очистки всех отмененных узлов в очереди синхронизации, чтобы найти узлы в не канцельном состоянии, он не пересекается спереди к спине, а сзади к фронту. Кроме того, когда каждый узел входит в очередь, его состояние ожидания равно 0. Только когда необходимо приостановить поток последующего узла, будет изменено состояние ожидания предыдущего узла на сигнал.
ПРИМЕЧАНИЕ. Все вышеперечисленные анализы основаны на JDK1.7, и будут различия между различными версиями, читатели должны обратить внимание.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.