AQS 是 java.util.concurrent.locks.AbstractQueuedSynchronizer
类的简称,它虽然只是一个类,但也是一个强大的框架,目的是为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量、事件,等等)提供一个框架,这些类同步器都依赖单个原子 int 值来表示状态。
AQS 实现了控制同步的框架,并定义抽象方法留给子类定义哪种状态意味着被获取或被释放,是个典型的模板方法实现。
概述
同步器一般包含两种方法,一种是acquire,另一种是release。acquire操作阻塞调用的线程,直到或除非同步状态允许其继续执行。而release操作则是通过某种方式改变同步状态,使得一或多个被acquire阻塞的线程继续执行。
同步器的基本思想
acquire操作:
// 循环里不断尝试,典型的失败后重试 while (synchronization state does not allow acquire) { // 同步状态不允许获取,进入循环体,也就是失败后的处理 enqueue current thread if not already queued; // 如果当前线程不在等待队列里,则加入等待队列 possibly block current thread; // 可能的话,阻塞当前线程 } // 执行到这里,说明已经成功获取,如果之前有加入队列,则出队列。 dequeue current thread if it was queued;
release操作:
update synchronization state; // 更新同步状态 if (state may permit a blocked thread to acquire) // 检查状态是否允许一个阻塞线程获取 unblock one or more queued threads; // 允许,则唤醒后继的一个或多个阻塞线程。
为了实现上述操作,需要下面三个基本组件的相互协作:
- 同步状态的原子性管理:怎么判断同步器是否可用的?怎么维护原子状态不会出现非法状态?怎么让其他线程看到当前线程对状态的修改?
- 线程的阻塞与解除阻塞:同步器不可用时,怎么挂起线程?同步器可用时,怎么恢复挂起线程继续执行?
- 队列的管理:有多个线程被阻塞时,怎么管理这些被阻塞的线程?同步器可用时,应该恢复哪个阻塞线程继续执行?怎么处理取消获取的线程?