Многопоточность Java: принципы инструментов параллелизма JUC

Java задняя часть
Многопоточность Java: принципы инструментов параллелизма JUC

Прежде всего, поделитесь всеми предыдущими статьями, ставьте лайки, добавляйте в избранное и пересылайте три раза подряд. >>>>😜😜😜
Сборник статей:🎁nuggets.capable/post/694164…
Github :👉github.com/black-ant
Резервное копирование CASE:👉git ee.com/ant black/wipe…

Введение

Воспользуйтесь свободным временем и быстро погасите задолженность перед этим. Это последняя часть многопоточного одноэтапного плана. Последующая многопоточность будет переведена на этап пересмотра и углубления. -заправка.

2. Введение в инструмент

сказал раньшеAQSКогда я упомянул эти классы, у этих классов есть свои особенности, которые очень подходят для конкретных сценариев, и раньше их было вполне удобно использовать в продакшене.

Мы обычно используем четыре типа инструментов параллелизма:

CyclicBarrier: пойдем вместе после школы

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

CountDownLatch: срабатывает, когда все прибывают

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

Semaphore

  • Семафор — это счетчик, контролирующий доступ к нескольким общим ресурсам.Как и CountDownLatch, по сути, это «общая блокировка».

Exchanger

  • Точка синхронизации для потоков, которые могут соединять и обменивать элементы в паре
  • Каждый поток представляет метод при входе в метод обмена, соответствует партнерскому потоку и получает объект своего партнера по возврату, Exchanger можно рассматривать как двунаправленную форму SynchronousQueue.

3. Принципиальный анализ

3 .1 CyclicBarrier

Функция:

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

Внутренний принцип:

Внутреннее использование реентерабельных блокировок ReentrantLock и Condition

Конструктор:

  • Циклический барьер (между сторонами):

    • Создайте новый CyclicBarrier, который будет запускаться, когда заданное количество участников (потоков) находится в состоянии ожидания,
    • Но это не выполняет заранее определенное действие, когда барьер активирован.
  • CyclicBarrier (между сторонами, Runnable барьерное действие):

    • Создайте новый CyclicBarrier, который будет запускаться, когда заданное количество участников (потоков) находится в состоянии ожидания,
    • И выполнить данную операцию барьера, когда барьер инициирован, что выполняется последним потоком, вошедшим в барьер.

Используйте переменные:

  • Переменная party : указывает общее количество перехваченных потоков.
  • переменная count: указывает оставшееся необходимое количество перехваченных потоков.
  • Переменная барьера: доступная для выполнения команда, полученная CyclicBarrier и используемая для предпочтительного выполнения барьерного действия, когда поток достигает барьера для обработки более сложных бизнес-сценариев.
  • переменная генерации: указывает на замену CyclicBarrier
// 常用方法 : 
M- await : 等待状态
M- await(long timeout, TimeUnit unit) : 等待超时
M- dowait
    - 该方法第一步会试着获取锁 
    - 如果分代已经损坏,抛出异常
    - 如果线程中断,终止CyclicBarrier
    - 进来线程 ,--count 
    - count == 0 表示所有线程均已到位,触发Runnable任务
    - 唤醒所有等待线程,并更新generation
    > 跳出等待状态的方法
        - 最后一个线程到达,即index == 0
        - 超出了指定时间(超时等待)
        - 其他的某个线程中断当前线程
        - 其他的某个线程中断另一个等待的线程
        - 其他的某个线程在等待barrier超时
        - 其他的某个线程在此barrier调用reset()方法。reset()方法用于将屏障重置为初始状态。
SC- Generation : 描述了 CyclicBarrier 的更新换代。
    - 在CyclicBarrier中,同一批线程属于同一代。
    - 当有 parties 个线程全部到达 barrier 时,generation 就会被更新换代。
    - 其中 broken 属性,标识该当前 CyclicBarrier 是否已经处于中断状态
M- breakBarrier : 终止所有的线程
M- nextGeneration : 更新换代操作
	- 1. 唤醒所有线程。
	- 2. 重置 count 。
	- 3. 重置 generation 。
M- reset : 重置 barrier 到初始化状态 
M- getNumberWaiting : 获得等待的线程数
M- 判断 CyclicBarrier 是否处于中断
    

CyclicBarrier.jpg

Случаи применения :

Использование Gitee CyclicBarrier

Дополнение к вопросу:


// 问题一 : 拦截的核心
1. 传入总得 Count 数
2. 每次进来都会 --count , 同时判断 count ==0 
3. 如果不为 0 ,当前线程就会阻塞

// 问题二 : 涉及源码
private final ReentrantLock lock = new ReentrantLock();
private final Condition trip = lock.newCondition();

3.2 CountDownLatch

Он позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках.

Инициализирует CountDownLatch с заданным счетчиком. Поскольку вызывается метод countDown(), прежде чем текущий счетчик достигнет нуля,Ожидание метода будет заблокировано. После этого все ожидающие потоки освобождаются, и все последующие вызовы await возвращаются немедленно.Это явление происходит только один раз, и счетчик не может быть сброшен. Если вам нужно сбросить счетчик, рассмотрите возможность использования CyclicBarrier..

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

// 内部主要方法
> CountDownLatch内部依赖Sync实现,而Sync继承AQS

> sync :
    : tryAcquireShared 获取同步状态
    : tryReleaseShared 释放同步状态
	
> await() :
    使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断
    : sync.acquireSharedInterruptibly(1);
    : 内部使用AQS的acquireSharedInterruptibly(int arg)
	
> getState()
    : 获取同步状态,其值等于计数器的值
    : 从这里我们可以看到如果计数器值不等于0,则会调用doAcquireSharedInterruptibly(int arg)

> doAcquireSharedInterruptibly
    : 自旋方法会尝试一直去获取同步状态
	
> countDown
    : CountDownLatch提供countDown() 方法递减锁存器的计数,如果计数到达零,则释放所有等待的线程
    : 内部调用AQS的releaseShared(int arg)方法来释放共享锁同步状态
    : tryReleaseShared(int arg)方法被CountDownLatch的内部类Sync重写    

CountDownLatch.jpg

использованная литература

Использование Gitee CountDownLatch

Суммировать

CountDownLatch внутренне реализован через общие блокировки. При создании экземпляра CountDownLatch вам необходимо передать параметр типа int: count, который является начальным значением счетчика, который также можно понимать как общее количество раз, когда может быть получена общая блокировка.

Когда поток вызывает метод await(), программа сначала определяет, равно ли значение count 0, и если оно не равно 0, она будет ждать, пока оно не станет равным 0 (PS: вы можете вызывать await для нескольких потоков)

Когда другие потоки вызывают метод countDown(), затем выполните снятие состояния общей блокировки, сделав значение счетчика – 1 (PS: countDown не блокирует)

Когда параметр count инициализируется при создании CountDownLatch,Должен быть поток count, вызывающий метод countDown, чтобы сделать счетчик count равным 0, блокировка будет снята, а ранее ожидавший поток продолжит работу.. Обратите внимание, что CountDownLatch нельзя откатить и сбросить.

3 .3 Semaphore

базовая точка

Семафор Семафор — это счетчик, контролирующий доступ к нескольким общим ресурсам, таким как CountDownLatch,По сути, это «общий замок»..

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

Семафор часто используется для ограничения количества потоков, которые могут получить доступ к определенным ресурсам (физическим или логическим).

Когда поток хочет получить доступ к общему ресурсу, он должен сначала получить семафор, когда семафор > 0, получить ресурс и сделать семафор - 1. Если значение Semaphore = 0, это означает, что все общие ресурсы заняты другими потоками, и поток должен ждать, пока другие потоки освободит ресурсы. Семафор +1, когда поток освобождает ресурсы

детали реализации

Semaphore предоставляет два конструктора:

  • Semaphore(intlets) : создает семафор с заданным количеством разрешений и настройкой несправедливой справедливости.
  • Semaphore(int permissions, boolean fair) : создает семафор с заданным количеством разрешений и заданными настройками справедливости.

Semaphore по умолчанию выбирает нечестные блокировки.

Когда семафор Semaphore = 1, его можно использовать как мьютекс. Среди них его состоянию эквивалентны 0 и 1. Когда = 1, это означает, что его могут получить другие потоки. Когда = 0, оно является исключительным, то есть другие потоки должны ждать.

//------ 信号量获取
> acquire()方法来获取一个许可
	: 内部调用AQS的acquireSharedInterruptibly(int arg),该方法以共享模式获取同步状态
	

> 公平 
    : 判断该线程是否位于CLH队列的列头
    : 获取当前的信号量许可
    : 设置“获得acquires个信号量许可之后,剩余的信号量许可数”
    : CAS设置信号量
> 非公平
    : 不需要判断当前线程是否位于CLH同步队列列头
     

Semaphore.jpg

3 .4 Exchanger

Точка синхронизации для потоков, которые могут соединять и обменивать элементы в паре

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

Exchanger, который позволяет обмениваться данными между параллельными задачами. : когда оба потока достигают точки синхронизации, они обмениваются структурами данных, поэтому структура данных первого потока переходит во второй поток, а структура данных второго потока — в первый поток.

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

3.5 Использование параллельных инструментов

@ GitHub.com/black-Anta/От…

Пополнить:

# Как понимают CountDownLatch и CyclicBarrier?

  • CyclicBarrier: ученики начальной школы отправляются на прогулку, считают количество учителей, когда выходят из автобуса,Количество людей, которые могут собраться вместе, чтобы посетить
  • CountDownLatch: учитель детского сада, чтобы отправить своих детей (ChildThread) после школы, запишите число, когда все ученики в школе,Учитель (BossThread) не работает
// 核心解释 : 
CyclicBarrier 就是一堵墙 , 人数到了所有线程才能一起越过墙
CountDownLatch 只是一个计数器 , 数目到了主线程才能执行

// 其他要点 : 
CyclicBarrier 可以重置计数 , CountDownLatch 不可以

Суммировать

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

обновить запись

  • 20210915 : Оптимизированная компоновка