AQS

什么是AQS

java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个同步框架,可以用来实现一个依赖状态的同步器。

AQS定义两种队列

同步等待队列

  • 主要用于获取锁失败时入队的线程。

条件等待队列

  • 调用await()的时候会释放锁,然后线程会加入到条件队列,调用singnal()唤醒的时候会把条件队列中的线程中的线程节点移动到同步队列中,等待再次获得锁。

AQS核心机制

  1. 状态(State):AQS通过一个volatile类型的整数state来表示同步状态。
  2. 队列(Queue):AQS维护了一个FIFO的等待队列,用于管理 等待获取同步状态的线程。每个节点(Node)代表一个等待的线程,节点之间通过next和prev指针链接。当一个线程获取同步状态失败时,它会被 添加到等待队列中,并自旋等待或者被阻塞,直到前面的线程释放同步状态。
  3. 独占模式和共享模式:
  1. 独占模式:只有一个线程能获取同步状态,例如ReentrantLock
  2. 共享模式:多个线程可以同时获取同步状态,例如Semaphore和RedadWriteLock

ReentrantLock的原理

ReentrantLock其实就是基于AQS实现的一个可重入锁,支持公司和非公平两种方式。

内部实现依靠一个state变量和两个等待队列 :同步队列和等待队列。

利用CAS修改state来争抢锁。

争抢不到则入同步队列等待,同步队列是一个双向链表。

条件condition不满足时则入等待队列等待,是个单身链接。

是否是公司锁的区别在于:线程获取锁时是加入到同步队列尾部还是直接利用CAS争抢锁。


Semaphore的原理?

Semaphore(信号量)是Java并发包中的一个同步工具类,用于管理一组许可(permits)。每个许可可以被一个线程持有,当许可被持有时,其它线程需要等待才能获取许可。即可以限制同时访问特定资源的线程数量,确保在特定时刻只有有限数量的线程能够访问资源。

CountDownLatch的原理?

CountDownLatch是 JUC中的一个同步辅助类,它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。CountDownLatch通过一个计数器来实现,计数器的初始值由构造方法传入。每当一个线程完成工作后,计数器会递减,所有等待的线程会被唤醒并继续执行。

主要功能:

  1. 等待事件完成:通过await()方法,线程可以等待其它线程完成某些操作。
  2. 递减计数器:其它线程在完成各自的任务后,通过调用countDown()方法将计数器减1.
  3. 线程同步:当计数器变为0时,所用调用了await()的线程将唤醒并继续执行。