1.简介
AQS(AbstractQueuedSynchronizer)本身是一个抽象类,主要的使用方法是继承它作为一个内部类,JDK中许多并发工具类的内部实现都依赖于AQS,如ReentrantLock, Semaphore, CountDownLatch等等。
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer
implements java.io.Serializable
2.实现思路:
AQS的实现依赖内部的同步队列(FIFO双向队列),线程首先会尝试获取锁,如果失败,则将当前线程以及等待状态等信息包成一个node节点加到同步队列尾部,接着会不断循环尝试获取锁(条件是当前节点为head的直接后继才会尝试),如果失败则会阻塞自己,直至被唤醒;而当持有锁的线程释放锁时,会唤醒队列中的后继线程。
2.1 主要作用:
1.同步状态的管理
2.线程的阻塞和唤醒
3.同步队列的维护
2.2 锁的获取
调用内部类的sync.acquire(1)方法,该方法会调用tryacquire()方法来试着获取独占锁,一般该方法需要重写
@Override
public void lock() {
sync.acquire(1);
}
@Override
protected boolean tryAcquire(int arg){
assert arg == 1;
System.out.println("111");
//原子设置当前状态
if(compareAndSetState(0,1)){
//原子操作
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
2.3 锁的释放
调用release()方法,该方法再调用tryRelease()方法。
3 API简介
- int getState(): 获取同步状态
- void setState(): 设置同步状态
- boolean compareAndSetState(int expect, int update):基于CAS,原子设置当前状态
自定义同步工具的话,一般都会基于覆盖以下几个方法来实现同步状态的管理
方法 | 描述 |
---|---|
boolean tryAcquire(int arg) | 试获取独占锁 |
boolean tryRelease(int arg) | 试释放独占锁 |
int tryAcquireShared(int arg) | 试获取共享锁 |
boolean tryReleaseShared(int arg) | 试释放共享锁 |
boolean isHeldExclusively() | 当前线程是否获得了独占锁 |
内嵌Node的定义
static final class Node {
/**
* 用于标记一个节点在共享模式下等待
*/
static final Node SHARED = new Node();
/**
* 用于标记一个节点在独占模式下等待
*/
static final Node EXCLUSIVE = null;
/**
* 等待状态:取消
*/
static final int CANCELLED = 1;
/**
* 等待状态:通知
*/
static final int SIGNAL = -1;
/**
* 等待状态:条件等待
*/
static final int CONDITION = -2;
/**
* 等待状态:传播
*/
static final int PROPAGATE = -3;
/**
* 等待状态
*/
volatile int waitStatus;
/**
* 前驱节点
*/
volatile Node prev;
/**
* 后继节点
*/
volatile Node next;
/**
* 节点对应的线程
*/
volatile Thread thread;
/**
* 等待队列中的后继节点
*/
Node nextWaiter;
/**
* 当前节点是否处于共享模式等待
*/
final boolean isShared() {
return nextWaiter == SHARED;
}
/**
* 获取前驱节点,如果为空的话抛出空指针异常
*/
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null) {
throw new NullPointerException();
} else {
return p;
}
}
Node() {
}
/**
* addWaiter会调用此构造函数
*/
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
/**
* Condition会用到此构造函数
*/
Node(Thread thread, int waitStatus