AbstractQueuedSynchronizer
AbstractQueuedSynchronizer
简称AQS,常见的锁ReetrantLock
就是AQS的实现,AQS的本质是一个双向链表。通过head
和tail
都可以操作整个队列。
+------+ prev +-----+ +-----+
head| | <---- | | <---- | | tail
+------+ +-----+ +-----+
在AQS中有主要通过静态内部类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;
// 等待节点的后继节点。如果当前节点是共享的,那么这个字段是一个SHARED常量,也就是说节点类型(独占和共享)和等待队列中的后继节点共用一个字段。(注:比如说当前节点A是共享的,那么它的这个字段是shared,也就是说在这个等待队列中,A节点的后继节点也是shared。如果A节点不是共享的,那么它的nextWaiter就不是一个SHARED常量,即是独占的。)
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() { // Used to establish initial head or SHARED marker
}
// 构造一个节点,添加到等待队列
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
// 构造一个节点,添加到Condition队列
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
AbstractQueuedSynchronizer
中的属性:
// 当前AQS的头部节点
private transient volatile Node head;
// 当前AQS的尾部节点
private transient volatile Node tail;
// 当前AQS的状态
private volatile int state;
并且分别提供了head
、tail
、state
的cas
方法。标明每次操作替换整个队列的头部和尾部节点的时候,都是原子性操作,而且Node
类中的关键属性,也都提供了cas
方法。
ReentrantLock与AQS
NonfairSync.lock()
final void lock() {
// CAS 尝试获取锁
if (compareAndSetState(0, 1))
// 当前线程获取锁成功
setExclusiveOwnerThread(Thread.currentThread());
// 获取锁失败
else
// 调用AQS的获取锁方法尝试获取锁。如果获取失败,则调用AQS的addWaiter方法,将当前线程添加到等待队列中。
acquire(1);
}
这里是非公平锁的源码,NonfairSync
继承了Sync
。Sync
也是ReentrantLock
的静态内部类。Sync
又继承于AbstractQueuedSynchronizer
。所以通过ReentrantLock
源码可以看到,利用了AQS将竞争锁失败的线程放入到AQS的等待队列中。其中还有一个公平锁FairSync
。
FairSync.lock()
final void lock() {
acquire(1);
}
与非公平锁的区别就是,没有先去通过CAS获取一遍锁,而是直接走AQS的方法获取锁。这样就保证了同一个线程不会因为每次释放锁而又能立马拿到锁,而是先去队列中排队,等待获取锁。保证了公平性。
AbstractQueuedSynchronizer.acquire(int arg)
public final void acquire(int arg) {
if (
// 尝试获取锁,获取成功返回true,凡是false
!tryAcquire(arg)
&&
// 如果获取失败,则将当前线程设置为独占锁添加到等待队列中
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)){
// 获取失败,中断当前线程。
selfInterrupt();
}
}