AQS学习笔记

AQS 的全称为(AbstractQueuedSynchronizer)这个类在 java.util.concurrent.locks 包下面

AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒 时锁分配的机制,这个机制 AQS 是用 CLH 队列锁实现的,即将暂时获取不到锁的线程加入到队列中。

AQS 定义两种资源共享方式

  1. Exclusive(独占)
    ReentrantLock
    又可分为公平锁和非公平锁,ReentrantLock 同时支持两种锁,下面以 ReentrantLock 对这两种锁的定义做介绍:
    公平锁FIFO,抢占资源是判断队列有没有等待线程 如果有就排队等待
    非公平锁:需要抢锁先经过两次CAS,当前线程抢不到进入队列等待唤醒,lock方法第一次cas是在tryAcquire之前,第二次cas在tryAcquire中

ReentrantLock 默认采用非公平锁,因为考虑获得更好的性能,构造方法通过 boolean 来决定是否用公平锁(传入 true 用公平锁)

  1. Share(共享)

Semaphore/CountDownLatch


image.png
image.png

Semaphore(信号量)-允许多个线程同时访问
synchronized 和 ReentrantLock 都是一次只允许一个线程访问某个资源,Semaphore(信号量)可以指定多个线程同时访问某个资源。


image.png

Semaphore 有两种模式,公平模式和非公平模式。

公平模式: 调用 acquire 的顺序就是获取许可证的顺序,遵循 FIFO;

非公平模式: 抢占式的。

CountDownLatch 的两种典型用法


image.png
image.png

其他 N 个线程必须引用闭锁对象,因为他们需要通知CountDownLatch对象,他们已经完成了各自的任务。这种通知机制是通过CountDownLatch.countDown()方法来完成的;每调用一次这个方法,在构造函数中初始化的 count 值就减 1。所以当 N 个线程都调 用了这个方法,count 的值等于 0,然后主线程就能通过 await() 方法,恢复执行自己的任务。

CyclicBarrier(循环栅栏)

CyclicBarrier 和 CountDownLatch 非常类似,它也可以实现线程间的技术等待,但是它的功能比CountDownLatch 更加复杂和强大。主要应用场景和 CountDownLatch 类似。

CountDownLatch的实现是基于AQS的,而CycliBarrier是基于 ReentrantLock(ReentrantLock也属于AQS同步器)和 Condition 的.

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障 拦截的线程才会继续干活。CyclicBarrier 默认的构造方法是 CyclicBarrier(int parties) ,其参数表示屏障拦截的线程数量,每个线程调用await 方法告诉 CyclicBarrier 我已经到达了屏障,然后当前线程被阻塞。


image.png

其中,parties 就代表了有拦截的线程的数量,当拦截的线程数量达到这个值的时候就打开栅栏,让所有线程通过。

CyclicBarrier 的应用场景


image.png
image.png

image.png

你可能感兴趣的:(AQS学习笔记)