AQS是一个FIFO的双向队列,它是实现同步器和并发包中的锁的基础框架。队列中的元素类型是Node类型。AQS的子类一般只需要重写tryAcquire(int arg)和tryRelease(int arg)两个方法即可。AQS维持了一个单一的状态信息state,可以通过getState、SetState、compareAndSetState函数修改其值,对于基于AQS实现的不同的同步器,state变量代表着不同的意义。线程同步的关键是对状态值state进行操作。
独占方式:
acquire:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
首先使用tryAcquire方法尝试获取资源,具体是设置状态变量state,成功则直接返回,失败则将当前线程封装成Node.EXCLUSIVE的Node节点插入到AQS阻塞队列的尾部。
release:
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
尝试使用tryRelease操作释放资源,是设置状态变量state的值。并激活AQS队列里面被阻塞的一个线程。
共享方式:
acquireShared:
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
使用tryAcquireShared尝试获取资源,成功则直接返回,失败失败则将当前线程封装成类型为Node.shared的Node节点插入到AQS阻塞队列的尾部。
releaseShare:
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
尝试使用tryReleaseShare操作释放资源,是设置状态变量state的值。并激活AQS队列里面被阻塞的一个线程。