在基于AQS
构建的同步器类中,最基本的操作包括各种形式的获取操作和释放操作。获取操作是一种依赖状态的操作,并且通常会阻塞。当使用锁或信号量时,“获取”操作的含义即获取的是锁或者许可,并且调用者可能会一直等待直到同步器类处于可被获取的状态。在使用CountDownLatch
时,“获取”操作意味着“等待并直到闭锁到达结束状态”,而在使用FutureTask
时,则意味着“等待并直到任务已经完成”。“释放”并不是一个可阻塞的操作,当执行“释放”操作时,所有在请求时被阻塞的线程都会开始执行。
如果一个类想成为状态依赖的类,那么它必须拥有一些状态。AQS
负责管理同步器类中的状态,它管理了一个整数状态信息,可以通过getState
,setState
以及compareAndSetState
等protected
类型方法来进行操作。这个整数可以用于表示任意状态。例如,ReentrantLock
用它来表示所有者线程已经重复获取该锁的次数,Semaphore
用它来表示剩余的许可数量,FutureTask
用它来表示任务的状态(尚未开始、正在运行、已完成以及已取消)。在同步器类中还可以自行管理一些额外的状态变量,例如,ReentrantLock
保存了锁的当前所有者的信息,这样就能区分某个获取操作是重入的还是竞争的。
一个获取操作包括两部分。首先,同步器类判断当前状态是否允许获得操作,如果是,则允许线程执行,否则获取操作将阻塞或失败。其次,就是更新同步器的状态,获取同步器的某个线程可能会对其他线程能否也获取该同步器造成影响。
1 | // AQS中获取操作和释放操作的标准形式 |
如果某个同步器支持独占的获取操作,那么需要实现一些保护方法,包括tryAcquire
、tryRelease
和isHeldExclusively
等,而对于共享获取的同步器,则应该实现tryAcquireShared
和tryReleaseShared
等方法。AQS
中的accquire
、acquireShared
、release
和releaseShared
等方法都将调用这些方法在子类中带有try
的版本来判断某个操作是否能执行。在同步器的子类中,可以根据其获取操作和释放操作的语义,使用getState
、setSate
以及compareAndSetSate
来检查和更新状态,并通过返回的状态值来告知基类“获取”或“释放”同步器的操作是否成功。