AQS
AQS即同步器,用于构建锁和同步器的抽象类,使用AQS能简单且高效地构建出应用广泛的大量的同步器。
核心思想
AQS核心思想:如果被请求的共享资源空闲,则把当前请求的线程设置为有效的线程,并且把共享资源的状态设置为锁定。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
关键成员变量state
1 | private volatile int state; //共享变量,使用volatile修饰保证线程可见性 |
AQS通过volatile int成员变量state来标识同步状态,使用CAS对该同步状态进行原子操作实现值的修改。通过FIFO队列来完成获取资源线程的排队工作
CLH队列
CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列,即不存在队列实例,仅存在节点间的关联关系。AQS把每条请求共享资源的线程封装成一个CLH锁队列的一个节点来实现锁的分配。
独占和共享
AQS定义了两种资源共享的方式:独占(只有一个线程能够执行)、共享(多个线程可以同时执行)。
独占可以分为公平锁和非公平锁
- 公平锁:按照线程在队列中的顺序,先到者先拿到锁;
- 非公平锁:无视队列顺序,谁抢到就是谁的。
两对方法
使用AQS实现自己的锁,依据资源的共享方式,需要实现不同的方法。
资源共享的方式为独占,则需要实现的方法如下
1 | tryAcquire(int) |
尝试获取资源,成功则返回true,失败则返回false。
1 | tryRelease(int) |
尝试释放资源,成功则返回true,失败则返回false。
资源共享的方式为共享,需要实现的方法如下
1 | tryAcquireShared(int) |
尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
1 | tryReleaseShared(int) |
尝试释放资源,成功则返回true,失败则返回false。
*总结:独占模式下主要实现:tryAcquire()和tryRelease()方法,共享模式下主要实现tryAcquireAndShared()和tryReleaseShared()方法,这些方法一般都是成对使用,但也有同时实现使用情形,例如:ReentrantReadWriteLock。*