AbstractQueuedSynchronizer 源码详解
AbstractQueuedSynchronizer 简述
AbstractQueuedSynchronizer
是juc
(java.util.concurrent
)包下的一个线程相关类,主要功能是作为同步队列器,后面简称为AQS
;
AQS
被多个线程类所使用,包括重入锁(ReentrantLock
),读写重入锁(ReentrantReadWriteLock
),信号量(Semaphore
),计数器(CountDownLatch
)等,这几种都是内部拥有对象属性Sync
,静态抽象类Sync
继承了AQS
;线程池(ThreadPoolExecutor
)中的私有内部类(Worker
,即线程任务,实现了Runnable
)也是继承了AQS
;
本篇文章将以重入锁(ReentrantLock
)为切入点,并通过解析ReentrantLock
中最基础的lock()
和unlock()
方法,来深入分析AQS
的源码;
源码分析
分析准备
在分析前需要以重入锁为基础,实现一个简单的Demo
类;
public class Demo {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Runnable runnable = () -> {
// 上锁
reentrantLock.lock();
for (int i = 0; i < 10000; i++) {
System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());
}
// 解锁
reentrantLock.unlock();
};
// 启动两个线程
new Thread(runnable, "thread-test-1").start();
new Thread(runnable, "thread-test-2").start();
}
}
执行代码,会发现线程2
会等待线程1
执行完毕后再继续执行,执行结果不做展示;
初始化 ReentrantLock
当创建一个ReentrantLock
对象时,其内部实际创建的是非公平锁对象(这里采用的是默认的构造方法);
// sync是ReentrantLock的内部类,并作为ReentrantLock的私有属性存在
private final Sync sync;
// 默认false, 使用非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
// true 公平锁,false 非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
Sync
也是继承了AbstractQueuedSynchronizer
;
abstract static class Sync extends AbstractQueuedSynchronizer {...}
当顺着构造方法向上追溯,会发现实际上执行的是AQS
的构造方法;
protected AbstractQueuedSynchronizer() { }
ReentrantLock 的 lock() 方法
ReentrantLock
的lock()
方法即为上锁操作;方法内部调用了Sync
的lock()
方法;
public void lock() {
sync.lock();
}
进入非公平锁的lock()
方法;
final void lock() {
// cas重入判断
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
Sync 的 lock() 方法
Sync
的lock()
方法,会执行AQS
中定义的compareAndSetState()
方法,首先会进行CAS
(比较替换)重入判断;传入一个期待值0
,若内存中的值等于0
,则将内存中的值更新为1
,并返回true
,更新失败则为false
;
protected final boolean compareAndSetState(int expect, int update) {
// 执行了Unsafe类中的compareAndSwapInt()方法
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
compareAndSetState()
方法内部执行了Unsafe
类中的compareAndSwapInt()
方法,compareAndSwapInt()
方法是一个native
方法,因此是原子性的;
注意,compareAndSwapInt()
方法也是实现CAS
的最常用方法;
若compareAndSetState()
方法更新成功,则表示可重入,否则表示当前已有其他线程抢占了锁资源,将执行acquire()
方法,进入等待重试逻辑;
方法中的stateOffset
值为state
属性在内存中的偏移量,即可理解为state
属性在内存中的存储位置,AQS
使用静态代码块的方式,已初始化了一系列属性的内存偏移值;
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
}
首先,当线程A
执行到lock()
方法时,此时无线程竞争锁,因此compareAndSetState()
方法成功替换state
属性值为1
(初始化AQS
时,stats
属性默认赋值为0
),返回true
;
private volatile int state;
state
属性由volatile
关键字修饰,因此对其他线程可见;
此时CAS
操作完成,将执行setExclusiveOwnerThread()
方法,传入当前线程对象Thread.currentThread()
;
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
此时,对AQS
中属性exclusiveOwnerThread
赋值为当前线程对象,此属性标识了当前独占的线程对象;
AQS 的 acquire() 方法
此时,若有线程B
也执行到了lock()
方法,同样首先进行了CAS
操作,但因为当前已有线程A
先抢占了锁(此时state
属性值为1
),因此CAS
操作失败,将执行acquire()
方法,传入参数1
;
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
acquire()
方法会进行重试判断操作;
AQS 的 tryAcquire() 方法
首先,将执行tryAcquire()
方法,tryAcquire()
方法在NonfairSync
类中被重写(FairSync
重写逻辑不做详解);
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
内部执行了Sync
中的nonfairTryAcquire()
方法;
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 获取状态
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 判断你是否是同一个线程对象(重入概念)
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
首先,会进行判断state
属性值是否为0
,即锁资源已释放(state
会在执行unlock()
方式时,重置为0
),这里主要是对一些线程任务逻辑处理很快的情况进行判断,进行再次CAS
重试,防止在线程B
正在进行判断的同时,线程A
已释放锁的情况,避免一些不必要的判断,可以更快的获取锁资源;若此时,CAS
成功,将线程B
设置为独占线程;
若state
不为0
,那么将判断当前线程是否与独占线程属性是同一个线程对象,若是则返回true
,并将state
状态加1
,记录重入次数,这里主要是锁重入机制的展现;
因为据统计,大部分情况下,程序执行的线程都只有一个线程,而获取释放锁的操作是重量级的,极耗性能,因此这里判断,若是同一个线程,就直接放行,此时就相当于无锁状态;
若上述判断都不成立,则表示,存在锁竞争的情况,将继续执行判断acquireQueued()
方法;
首先会执行addWaiter(Node.EXCLUSIVE)
方法;
在解释addWaiter()
方法之前需要先详细描述一下AQS
中最关键的内部类Node
,这也是AQS
同步队列中的基础;
线程节点 Node 类
Node
中封装了当前线程对象,并与其他Node
对象组成了一个双向链表,这也就是AQS
中同步队列的含义;
Node
中比较关键的属性表示线程节点的等待状态,主要拥有五种状态;
CANCELLED(1)
,表示当前节点已取消调度;当timeout
线程超时或被中断(响应中断的情况下),会触发变更为此状态,进入该状态后的节点将不会再变化;SIGNAL(-1)
,表示后继节点在等待当前节点唤醒;后继节点入队时,会将前继节点的状态更新为SIGNAL
;CONDITION(-2)
,表示节点等待在Condition
上,当其他线程调用了Condition
的signal()
方法后,CONDITION
状态的节点将从等待队列转移到同步队列中,等待获取同步锁;PROPAGATE(-3)
,共享模式下,前继节点不仅会唤醒其后继节点,同时也可能会唤醒后继的后继节点;0
,新节点入队时的默认状态;
在AQS
中,也通过标识了头尾Node
节点,来确定Node
双向链表的顺序;节点head
和tail
通过修饰volatile
,对所有线程可见;
注,修饰符transient
表示当前属性不会被序列化;
private transient volatile Node head;
private transient volatile Node tail;
Node节点的详细源码,请查看附录源码中的线程节点Node
章节;
AQS 的 addWaiter() 方法
紧接上文,继续分析addWaiter()
方法;
// Node中的属性和构造方法
static final Node EXCLUSIVE = null;
Node nextWaiter;
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
这里会将当前线程封装为一个Node
节点,并设置属性thread
为当前线程,前置节点prev
指向AQS
中的尾部节点tail
;
若AQS
中的尾部节点tail
为空,说明同步队列还初始化,则执行enq()
方法;否则将Node
节点前置节点prev
指向尾节点;之后执行compareAndSetTail()
方法,更新tail
属性指向当前节点;
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
compareAndSetTail()
同样是CAS
操作,将tail
指向当前Node
节点(原子性更新操作,防止多个线程同时操作tail
属性),若成功,则表示向同步队列的尾部插入Node
节点成功,否则将继续执行enq()
方法;
AQS 的 enq() 方法
AQS
中的enq()
方法是个核心方法,主要处理了同步队列的初始化,以及向尾部添加节点的操作;
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
这里,enq()
方法采用了自旋的方式,尝试向同步队列中添加节点;这里主要分为两种情形;
一,同步队列未初始化;此时,tail
为空,这里会通过new Node()
初始化一个头节点,注意,这里初始化的Node节点是一个空节点,未指定任何属性变量,AQS
中的head
和tail
同时指向这个空节点;
之后会再次自旋,将当前传入的Node
节点的前置节点指向刚刚初始化的空节点,并再次CAS
,将tail
替换为当前Node
,并将head
节点的下个节点next
指向当前Node
;
二,同步队列已初始化;此时,会获取节点tail
,并将当前节点的前置节点prev
指向尾部节点,CAS
操作替换tail
为当前Node
,并将prev
的next
节点指向当前Node
;
当上述操作完成后,则表示当前Node
已成功插入,否则将继续自旋,直到插入完成;
AQS 的 acquireQueued() 方法
当addWaiter()
执行成功,将继续执行判断方法acquireQueued()
;
final boolean acquireQueued(final Node node, int arg) {
// 取消标志
boolean failed = true;
try {
// 中断标志
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
// 这里是一个对标记为取消的节点的操作,lock()方法中未涉及,这里不作详解
cancelAcquire(node);
}
}
// Node中的
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
这里同样采用自旋的方式,首先调用了Node
类中的predecessor()
,predecessor()
方法用于获取当前节点Node
的前置节点prev
;
之后继续判断前置节点prev
是否指向head
节点,如果是head
节点,则表示当前节点为同步队列中的第二个节点,此时便拥有资格去竞争锁资源(可能是head
节点释放完资源唤醒当前节点,当然也可能是head
被interrupt
了),则再次调用tryAcquire()
方法,尝试去获取锁(即当前线程会去尝试CAS
操作state
状态更新为1
,或者判断是否是重入状态);
若成功,则竞争锁成功,将当前Node
设置为head
节点,并将原head
节点的next
设置为null
,此处是为了帮助GC
,防止过多的原head在内存中占用资源;
若抢占未成功,将执行后续判断,首先执行shouldParkAfterFailedAcquire()
方法;
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL) // Node.SIGNAL = -1
return true;
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
private static final boolean compareAndSetWaitStatus(Node node, int expect, int update){
return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
}
shouldParkAfterFailedAcquire()
主要是判断当前节点的前置节点的状态waitStatus
;
Node.SIGNAL = -1
表示后续节点在等待当前节点唤醒,直接则返回true
,表示当前节点在等待前置节点唤醒;
当waitStatus > 0
,主要指的是CANCELLED = 1
状态,表示当前Node
取消了调度,因此当前Node
的prev
属性向前寻找前置Node
,直到向前找到waitStatus
不再是取消状态的Node
,并做双向关联,将已取消的节点从链表中去除,重新形成新的Node
链表;
若前置节点Node
的prev
为0,-2,-3
时(waitStatus
为-2,-3
在当前普通的lock()
方法中未涉及到),则会将前置节点的状态变更为-1
;
因此在lock()方法中,同步队列最终所有的节点的waitStatus
都将被设置为-1
;
当shouldParkAfterFailedAcquire()
返回true
,将继续执行parkAndCheckInterrupt()
;
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
parkAndCheckInterrupt()
可以看到,到这一步时,当前会pack()
当前线程,线程进入休眠,此时,等待unlock()
方法将线程唤醒;
公平锁FairSync与非公平锁NonfairSync的区别
经过上述对ReentrantLock
的加锁逻辑进行了剖析,可以看出,非公平锁NonfairSync
在进入同步队列前会进行多次cas
重入判断,即竞争锁的动作,只有当这几次竞争均失败后,才会进入同步队列等待,之后按顺序获取锁资源,即新加入的线程会与同步队列中头部Node
线程竞争锁资源(排除掉head
哨兵空节点),同步队列中线程Node
按顺序依次获取竞争锁资源的资格;
公平锁FairSync
则是直接进入同步队列,不参与竞争锁资源的操作,按队列顺序获取锁资源;
ReentrantLock 的 unlock() 方法
AQS 的 release() 方法
ReentrantLock
中的释放锁方法unlock()
,内部是直接执行了AQS
中的release()
方法;
public void unlock() {
sync.release(1);
}
// AQS中定义的方法
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
Sync 的 tryRelease() 方法
首先,执行了tryRelease()
方法,tryRelease()
在Sync
中被重写;
// Sync中重写了tryRelease()
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
可以看到参数releases
传入的值为1
,AQS
的state
属性会进行减一的操作,并会校验当前线程是否与AQS
的当前的独占线程是同一线程;
若state
减一之后值为0
,则表示当前线程已执行完毕,将释放锁资源,并将AQS
的独占线程标识重置为null
,state重置为0
,此时表示当前没有加锁,后续被唤醒的线程节点,以及正在执行lock()
方法还没进入队列的线程可以竞争锁资源;
注意,之前说过重入锁的机制,若同一线程连续的加锁,将不会阻塞当前线程的执行,而是将state
进行加一操作,因此,若对同一锁多次执行lock()
方法,就需要同样数量的unlock()
来释放锁,否则将会产生死锁;
那么,最开始的Demo
方法进行改造,即为;
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Runnable runnable = () -> {
// 上锁
try {
reentrantLock.lock();
System.out.println("加了第一遍锁!");
reentrantLock.lock();
System.out.println("加了第二遍锁!");
for (int i = 0; i < 100; i++) {
System.out.println("Thread.currentThread().getName() = " + Thread.currentThread().getName());
}
} finally {
// 解锁,需要与lock()方法数量一致
reentrantLock.unlock();
reentrantLock.unlock();
}
};
// 启动两个线程
new Thread(runnable, "thread-test-1").start();
new Thread(runnable, "thread-test-2").start();
}
若对同一锁的unlock()
数量少于lock()
,则会发生死锁,若多于,则会报非法监视器状态异常IllegalMonitorStateException
如果去查看jvm
底层源码,就会发现jvm
在创建每一个对象时都会生成一个对象监视器monitor
,这也是为什么所有对象都可以作为锁对象,并且这也就是为什么wait()
,notify()
等线程相关的方法会定义在Object
中,所有对象都可以调用的原因;
AQS 的 unparkSuccessor() 方法
当tryRelease()
方法执行成功,则会获取head
节点,并判断head
节点的waitStatus
不为空,若判断为true
,则执行unparkSuccessor()
方法;
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
unparkSuccessor()
方法的作用主要是为了将后继节点唤醒,会将head
节点作为参数传入;
首先会判断是否head
节点的waitStatus < 0
(即-1,-2,-3
,状态为-1
表示取消,之前已经被从队列中去除了),若是则将waitStatus
更新为初始状态0
;之后会获取head的后继节点,即队列的第二个节点;
若后继节点为空或者后继节点的状态大于0
,即取消状态,则会从队列的尾部tail
(当head
、tail
指向同一个节点,即队列中只有一个节点时,不会进入循环)向前遍历,排除waitStatus
为取消状态的节点,直到遍历到head
节点前,即找到队列第二个节点;
之后,若后继节点不为空,则执行LockSupport.unpark()
方法,唤醒后继节点中的线程,此时后继节点开始竞争锁资源,后继节点会从之前acquireQueued()
方法中被park()
处继续执行自旋,尝试获取锁资源,若获取成功则将后继节点设置为head
,否则,将再次被park()
,等待下一次被唤醒;
至此,完整的加锁解锁逻辑已经逐步分析完毕;AQS
中还有内部类ConditionObject
,内部维护了AQS
的等待队列,具体的实现原理不再在这里赘述,可以自行查看源码,其大致原理相似;
所以,今天的AQS
源码,你学会了吗?
附录 源码
ReentrantLock 源码总览
下面展示出了ReentrantLock
的全部源码;
重入锁 ReentrantLock
ReentrantLock
内部定义了Sync
对象属性,Sync
是一个抽象类,拥有两个实现,非公平锁NonfairSync
和公平锁FairSync
;ReentrantLock
默认使用的是非公平锁,可以通过在构造方法中传递布尔值,指定ReentrantLock
使用的锁类型;
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
private final Sync sync;
// 默认false, 使用非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
// true 公平锁,false 非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
// 加锁方法
public void lock() {
sync.lock();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
// 解锁方法
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
public int getHoldCount() {
return sync.getHoldCount();
}
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
public boolean isLocked() {
return sync.isLocked();
}
public final boolean isFair() {
return sync instanceof FairSync;
}
protected Thread getOwner() {
return sync.getOwner();
}
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
public final int getQueueLength() {
return sync.getQueueLength();
}
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
}
抽象同步锁类 Sync
抽象类Sync
是ReentrantLock
中定义的内部类,并作为ReentrantLock
的私有属性存在;Sync
有两个实现,非公平锁NonfairSync
和公平锁FairSync
;
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
abstract void lock();
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
Sync 锁实现
非公平锁NonfairSync
和公平锁FairSync
是ReentrantLock
中的静态内部类,分别实现了Sync
中的lock()
和AQS
中的tryAcquire()
方法;
非公平锁 NonfairSync
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
公平锁 FairSync
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
AbstractQueuedSynchronizer 源码总览
下面先简单AQS
源码进行展示;
队列同步器 AbstractQueuedSynchronizer
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer() { }
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
static final long spinForTimeoutThreshold = 1000L;
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // Record old head for check below
setHead(node);
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())
doReleaseShared();
}
}
private void cancelAcquire(Node node) {
if (node == null)
return;
node.thread = null;
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
Node predNext = pred.next;
node.waitStatus = Node.CANCELLED;
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
return true;
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
public final boolean hasQueuedThreads() {
return head != tail;
}
public final boolean hasContended() {
return head != null;
}
public final Thread getFirstQueuedThread() {
return (head == tail) ? null : fullGetFirstQueuedThread();
}
private Thread fullGetFirstQueuedThread() {
Node h, s;
Thread st;
if (((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null) ||
((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null))
return st;
Node t = tail;
Thread firstThread = null;
while (t != null && t != head) {
Thread tt = t.thread;
if (tt != null)
firstThread = tt;
t = t.prev;
}
return firstThread;
}
public final boolean isQueued(Thread thread) {
if (thread == null)
throw new NullPointerException();
for (Node p = tail; p != null; p = p.prev)
if (p.thread == thread)
return true;
return false;
}
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}
public final boolean hasQueuedPredecessors() {
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
public final int getQueueLength() {
int n = 0;
for (Node p = tail; p != null; p = p.prev) {
if (p.thread != null)
++n;
}
return n;
}
public final Collection<Thread> getQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
}
public final Collection<Thread> getExclusiveQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (!p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
public final Collection<Thread> getSharedQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
public String toString() {
int s = getState();
String q = hasQueuedThreads() ? "non" : "";
return super.toString() +
"[State = " + s + ", " + q + "empty queue]";
}
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
return findNodeFromTail(node);
}
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
final boolean transferForSignal(Node node) {
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
final boolean transferAfterCancelledWait(Node node) {
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
public final boolean owns(ConditionObject condition) {
return condition.isOwnedBy(this);
}
public final boolean hasWaiters(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.hasWaiters();
}
public final int getWaitQueueLength(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitQueueLength();
}
public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitingThreads();
}
// 初始赋值了一系列内存偏移量
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
}
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
private static final boolean compareAndSetWaitStatus(
Node node, int expect, int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset,expect, update);
}
private static final boolean compareAndSetNext(
Node node, Node expect, Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
}
线程节点 Node
Node
类是AQS
中的静态内部类,也是AQS
中最为关键的类;
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() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
ConditionObject类
ConditionObject
是AQS
中的内部类,主要是为并发编程中的同步提供了等待通知的实现方式,可以在不满足某个条件的时候挂起线程等待,直到满足某个条件的时候在唤醒线程;
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
private transient Node firstWaiter;
private transient Node lastWaiter;
public ConditionObject() { }
private Node addConditionWaiter() {
Node t = lastWaiter;
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
private void doSignalAll(Node first) {
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
transferForSignal(first);
first = next;
} while (first != null);
}
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignalAll(first);
}
public final void awaitUninterruptibly() {
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if (Thread.interrupted())
interrupted = true;
}
if (acquireQueued(node, savedState) || interrupted)
selfInterrupt();
}
private static final int REINTERRUPT = 1;
private static final int THROW_IE = -1;
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return deadline - System.nanoTime();
}
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (System.currentTimeMillis() > abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
LockSupport.parkUntil(this, abstime);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
timedout = transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
return sync == AbstractQueuedSynchronizer.this;
}
protected final boolean hasWaiters() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
return true;
}
return false;
}
protected final int getWaitQueueLength() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int n = 0;
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
++n;
}
return n;
}
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
if (t != null)
list.add(t);
}
}
return list;
}
}