上文详述了synsynchronized的原理及实现【JAVA并发之Synchronized】,虽然在JDK1.6对其进行了大量优化,但是还是存在缺陷:缺少了获取锁与释放锁的可操作性,可中断、超时获取锁,且它为独占式在高并发场景下性能大打折扣。而java.util.concurrent(简称JUC)下的Lock类解决了这些问题,Lock类的基础之一为AQS,此文将介绍AQS的原理及底层实现。
AQS:全称AbstractQueuedSynchronizer,即队列同步器。它是构建锁或者其他同步组件的基础框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等),是JUC并发包中的核心基础组件。
本部分主要介绍要了解AQS所需要知道的一些前置知识,如CLH同步锁,LockSupport类
CLH同步锁
CLH同步锁:是一种基于链表的可扩展、高性能、公平的自旋锁,申请线程只在本地变量上自旋,它不断轮询前驱的状态,如果发现前驱释放了锁就结束自旋。
public class CLHLock {
public static class CLHNode {
private boolean isLocked = true; // 默认是在等待锁
}
@SuppressWarnings("unused" )
private volatile CLHNode tail ;
private static final AtomicReferenceFieldUpdater UPDATER = AtomicReferenceFieldUpdater
. newUpdater(CLHLock.class, CLHNode .class , "tail" );
public void lock(CLHNode currentThreadCLHNode) {
// 把this里的"tail" 值设置成currentThreadCLHNode
CLHNode preNode = UPDATER.getAndSet( this, currentThreadCLHNode);
if(preNode != null) {//已有线程占用了锁,进入自旋
while(preNode.isLocked ) {
}
}
}
public void unlock(CLHNode currentThreadCLHNode) {
// 如果队列里只有当前线程,则释放对当前线程的引用(for GC)。
if (!UPDATER .compareAndSet(this, currentThreadCLHNode, null)) {
// 还有后续线程
currentThreadCLHNode. isLocked = false ;// 改变状态,让后续线程结束自旋
}
}
}
LockSupport类
AQS并采用该模式LockSupport.park() 和 LockSupport.unpark() 的本地方法来实现线程的阻塞和唤醒。其特点详见使用LockSupport唤醒指定线程
AQS为了维护线程直接对锁的竞争关系,使用了如下队列,图是在源码注释上稍加改动(表述next节点)。
* +------+ prev +-----+ +-----+
* head | | <---- | | <---- | | tail
* | | ----> | | ----> | |
* +------+ next +-----+ +-----+
其代码如下:
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;
……
}
此双向链表,head与tail为两个头结点,为便于称呼,本文将head节点称为头结点,tail节点称为尾节点。
head节点是一个空节点,代表当前持有锁的线程,每当有线程获取锁失败,则将其加入到队尾,变为tail节点。
每个节点中的waitStatus变量,用于描述节点当前的状态,一共有5中状态:
CANCELLED 取消状态
SIGNAL 等待触发状态
CONDITION 等待条件状态,用于等待队列
PROPAGATE 用于shared锁队列
0:以上都不是
CANCELLED 是取消状态,当线程出现异常或自己中断时处于此状态。
SIGNAL 是等待触发状态,等待获取锁。
CONDITION 是条件队列中的线程状态
PROPAGATE 状态是支持其他扩展操作
等待队列是FIFO先进先出,只有前一个节点的状态为SIGNAL时,当前节点的线程才能被挂起。
SHARED 与EXCLUSIVE 代表锁的模式,分布代表共享锁与独占锁。
nextWaiter的值有三种情况:SHARED,null,其他
SHARED:表示当前节点是共享模式
null:当前节点是独占模式
其他:当前节点是独占模式,不过这个值也是Condition队列的下一个节点
AQS类的核心属性如下:
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) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
AQS使用一个int成员变量state表示同步状态,通过变种CLH队列(FIFO,双向链表)来完成排队工作。state,head,tail属性都使用volatile修饰,使得多线程之间可见。提供getState,setState,compareAndSetState方法来对state进行操作。
AQS中定义了如下方法供子类实现:
protected boolean isHeldExclusively() {//该线程是否正在独占资源。只有用到condition才需要去实现它。
throw new UnsupportedOperationException();
}
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();
}
用于支持独占锁与共享锁的操作(需要子类根据自身需求实现),将在下一篇博文中具体讲述实现的实例。
一、获取锁(上锁)过程
跟踪源码需要一个入口,这里通过从最上层作为入口(以ReentrantLock的公平锁为例(只作为切入,具体见下一篇博文)
//ReentrantLock的lock方法
public void lock() {
sync.lock();
}
//ReentrantLock的内部类sync的lock方法,实现AQS类
final void lock() {
acquire(1);
}
//AQS提供的模板方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
通过上述源码,有四个关键函数tryAcquire、addWaiter、acquireQueued、selfInterrupt,下面一一分析。
另,acquire的参数arg,是重入的次数,当锁持有者需要获取锁的时候,则要将锁的state加上arg的值。上述实现传入参数为1。
1.tryAcquire
tryAcquire(arg)方法上文已提及,是AQS的对外提供的方法,需要子类实现(上文已给出源码,只抛出异常),此处还是以ReentrantLock的公平锁FairSync为例static final class FairSync extends Sync
。
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;
}
getState()是获取锁的状态,表示锁当前是否被持有,为0时表示没有线程持有锁,此时当前线程会去争取锁的持有权,大于0表示该锁被持有次数。
若c=0,则通过hasQueuedPredecessors方法(AQS类)判断队列中是否有排在当前线程之前的线程。
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
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());
}
若有,放弃争抢锁(返回false);若无,将state更改为acquires,并调用setExclusiveOwnerThread()方法将当前线程设为锁的拥有者(同包下的AbstractOwnableSynchronizer类中),防止volatile字段被其他线程修改。
若c!=0,则判断当前线程是否是锁的拥有者。若是,则是重入,state+重入次数acquires;若不是,则获取锁失败,返回false。另,当state+acquires之后小于0,则代表数据溢出(此处初看看似没有必要【锁的持有次数不会溢出int类型】,仔细琢磨却充分反应了程序设计的严谨性)。
2.addWaiter
addWaiter(Node.EXCLUSIVE)方法AQS中实现的方法,作用是快速添加一个节点,代码如下:
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 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;
}
}
}
}
快速插入队列:判断队列是否为空,若非空,直接将新节点插入队尾成为tail节点;否则,通过enq(node)方法(AQS实现)将当前节点添加至队列中。
enq():为空则初始化队列,然后再将该节点node设置成队尾节点tail。考虑到多线程同时入队,初始化及设置操作均使用CAS,使用无限循环保证最终成功(每次循环前都需要判断是否为空),因此效率较慢。
3.acquireQueued
acquireQueued(node, arg)方法位于AQS中,同步队列中的节点以自旋方式获取锁。如果获取不到则阻塞节点中的线程,而被阻塞的线程的唤醒主要依靠前驱节点的出队或阻塞线程被中断来实现。返回值表示在线程等待过程中,是否有另一个线程调用该线程的interrupt方法,发起中断。
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);
}
}
节点入队后,不是立马挂起而是判断是否能获取锁,因为可能在这过程中锁释放了。
若该节点的上一个节点是head,则可以尝试获取锁(上述tryAcquire方法)。若获取成功,则将该节点设置为头结点,并将其next引用设为null(方便GC),将最终失败标志设为false。
若在获取锁的过程中发生异常(在tryAcquire中抛出,用于中断线程),则调用cancelAcquire方法,在5详述。
若该节点的上一个节点不为head或获取锁失败,则进行是否挂起的判断(shouldParkAfterFailedAcquire,AQS实现)。
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;
}
若该节点的上一个节点状态为SIGNAL(-1),则返回true,将其挂起。
若该节点的上一个节点状态大于0(只有CANCELLED),则证明上一个节点放弃锁的竞争,继续向前追溯其他节点,直至找到一个状态不大于0的节点,将其放在该节点后,并返回false,不挂起继续尝试一次获取锁。
否则,将该节点的状态使用CAS置为SIGNAL,并返回false,不挂起继续尝试一次获取锁。
将线程挂起的操作如下:
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
使用LockSupport实现阻塞,它会设置一个AQS的blocker,让队列里的线程阻塞在一个地方,然后返回线程是否中断的判断状态。
4.selfInterrupt()
selfInterrupt()是AQS类中的一个方法,用于当前线程休眠
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
acquireQueued会返回boolean值表示在线程等待过程中,是否有另一个线程调用该线程的interrupt方法,发起中断。如果有,则发起中断。
5.cancelAcquire()
cancelAcquire()方法在AQS中,此方法用于将某节点的状态设置为CANCELLED,表示已经从队列中删除,不再唤醒。
private void cancelAcquire(Node node) {
if (node == null)
return;
node.thread = null;//将node的线程属性置空
// 跳过那些已取消的节点,在队列中找到在node节点前面的第一次状态不是已取消的节点
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
Node predNext = pred.next;// 记录pred原来的下一个节点,用于CAS函数更新时使用
node.waitStatus = Node.CANCELLED;//将node的状态置为CANCELLED
if (node == tail && compareAndSetTail(node, pred)) {
// 如果node节点是队列尾节点,那么就将pred节点设置为新的队列尾节点,并且设置pred节点的下一个节点next为null
compareAndSetNext(pred, predNext, null);
} else {
/**
* 对node的前一个节点pred进行判断
* 若pred非空,不是头结点,状态为SIGNAL或能设置为SIGNAL,则将node的下一个结点设为pred的下一个结点
* 否则,唤醒node的下一个非取消状态的结点
*/
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的下一个结点置空,辅助GC
node.next = node; // help GC
}
}
对node自身的操作:将node的thread属性置空,waitStatus属性置为CANCELLED,next结点指向自身(方便GC)
对影响的其他节点操作:
过程总结:
此处再贴一次总代码,方便总结顺序:
final void lock() {
acquire(1);
}
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
二、释放锁过程
当获取锁成功,任务执行结束,就需要释放锁,此处同上以ReentrantLock的公平锁为例
//ReentrantLock的unlock方法
public void unlock() {
sync.release(1);
}
//ReentrantLock的内部类sync的unlock方法,实现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;
}
通过上述源码,有四个关键函数tryRelease、unparkSuccessor下面一一分析。
另,release的参数arg,是重入的次数,当锁持有者需要释放锁的时候,则要将锁的state减去arg的值。上述实现传入参数为1。
1.tryRelease()
tryRelease(arg)方法上文已提及,是AQS的对外提供的方法,需要子类实现(上文已给出源码,只抛出异常),此处还是以ReentrantLock的锁为例static final class Sync extends AbstractQueuedSynchronizer
。
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;
}
以上源码将state的值减少释放次数,如果减少次数到0,则将锁的拥有者置空,返回成功与否。
2.unparkSuccessor()
unparkSuccessor()实现在AQS中,用于唤醒node的下一个非CANCELLED状态节点。代码如下:
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);
}
通过CAS修改节点的waitStatus,然后将后续节点去除,这里唤醒后续的第一个非CANCELLED节点。
三、一定时间内获取锁
为了支持扩展功能,AQS提供了在一定时间内获取锁的方法,这里跟上文一样以ReentrantLock为例。
ReentrantLock对外提供该的方法,用于在指定时间内获取锁。传入参数为超时时间(timeout:时间数值,unit:时间单位)。
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
1.tryAcquireNanos()
tryAcquireNanos()方法是AQS内置实现的,用于在指定时间(nanosTimeout)内获取指定资源数(arg)。源码如下:
public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
// 如果当前线程中断标志位是true,那么直接抛出中断异常
if (Thread.interrupted())
throw new InterruptedException();
// 先调用tryAcquire方法,尝试获取独占锁,返回true,表示获取到锁。
// 否则调用doAcquireNanos方法获取锁
return arg(arg) ||doAcquireNanos(arg, nanosTimeout);
}
步骤如下:
2.doAcquireNanos()
doAcquireNanos()方法是AQS内置实现的,用于尝试一定时间(nanosTimeout)内获取指定资源数(arg)。获取过程中发生中断则抛出异常。源码如下:
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);
}
}
步骤如下:
共享锁的获取与释放与独占锁很类似,看AQS定义的以下四个方法就明白了差不多了。
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();
}
一、获取锁过程
通过上述代码看出,tryAcquire与tryAcquireShared方法只是返回值不同,在共享锁中,返回值含义:
获取共享锁的过程总结就是:
源码如下:
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
tryAcquireShared(arg) 【此方法需要子类实现】 获取锁,获取成功结束,获取失败进入doAcquireShared(arg)方法
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 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();
}
}
其中,与独占锁区别在于:
注意:假如head释放了3个资源,而n1需要5个,n2需要1个。head释放资源时唤醒n1线程,n1发现资源不够,是唤醒n2还是n1继续等待?答案是n1继续等待其他线程释放资源。这从代码中能看出来。
二、释放锁过程
共享锁的释放过程与独占锁一样也是:释放掉资源后,唤醒后继。
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
其中,与独占锁区别在于:独占模式只有在state=0的情况下,才会唤醒其他线程;而共享模式则是由多的资源就会唤醒后续线程,其实质就是控制一定量的线程并发执行。
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;
unparkSuccessor(h);//唤醒后续线程
}else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue;
}
if (h == head)
break;
}
}
Condition是为了实现线程之间相互等待的问题。注意Condition对象只能在独占锁中才能使用。
场景:有两个线程,生产者线程,消费者线程。当消费者线程消费东西时,发现没有东西,这时它就要等待,让生产者线程生产东西后,在通知它消费。因为操作的是同一个资源,所以要加锁,防止多线程冲突。而锁在同一时间只能有一个线程持有,所以消费者在让线程等待前,必须释放锁,且唤醒另一个等待锁的线程。
AQS内部实现:
一、await
await()让当前持有锁的线程释放锁,并唤醒一个在CLH队列上等待锁的线程,再为当前线程创建一个node节点,插入到Condition队列(注意不是插入到CLH队列中),具体实现代码如下:
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)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
上述代码中用到的常量
REINTERRUPT(1) : 中断请求在signalled之后
THROW_IE(-1) :中断请求在signalled(即调用signal或signalAll)之前
在上述过程中,用到的方法有addConditionWaiter、fullyRelease、isOnSyncQueue 、checkInterruptWhileWaiting、unlinkCancelledWaiters、reportInterruptAfterWait方法,下文一一描述。
1.addConditionWaiter()
为当前线程创建新的Node节点,并且将这个节点插入到Condition队列中,具体代码如下:
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;
}
步骤描述如下:
2.fullyRelease()
fullyRelease()方法用于释放当前线程占有的锁,并唤醒CLH队列中的一个线程,具体代码如下:
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;
}
步骤描述如下:
3.isOnSyncQueue ()
isOnSyncQueue ()方法用于判断当前节点是否在CLH队列中,具体代码如下:
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null)
return true;
return findNodeFromTail(node);
}
// 在同步队列中从后向前查找节点node,如果找到返回true,否则返回false
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
步骤描述如下:
4.checkInterruptWhileWaiting()
isOnSyncQueue ()用于判断当前线程是否产生中断请求,且中断请求发生在signalled之前还是之后, 若无则返回0,若发生在signalled之前返回-1,发送在之后返回1,具体代码如下:
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :0;
}
// 等待节点node存放到同步队列中,如果是当前线程插入的,返回true,如果是另一个线程插入的,返回false。
final boolean transferAfterCancelledWait(Node node) {
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
// 如果节点node不在同步队列中,当前线程让出执行权
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
此方法就是两个三目运算符,步骤不用描述
5.unlinkCancelledWaiters()
unlinkCancelledWaiters()方法用于清除Condition队列中waitStatus不是CONDITION的节点,具体代码如下:
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;
}
}
步骤描述如下:
6.reportInterruptAfterWait()
reportInterruptAfterWait()方法用于需要抛出异常或中断该线程,具体代码如下:
private void reportInterruptAfterWait(int interruptMode) throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
步骤描述如下:
二、signaled
signaled分为signal()和signalAll ()方法,类似于notify与notifyAll的唤醒,不过在这里它没有唤醒任何线程,而是将Condition队列上的等待节点插入到CLH队列中,所以当持有锁的线程执行完毕释放锁时,就会唤醒CLH队列中的一个线程,这个时候才会唤醒线程。
1.signal()
signal()方法将Condition队列中的first节点插入到CLH队列中,具体代码如下:
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
// 将Condition队列中的first节点插入到CLH队列中
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) && (first = firstWaiter) != null);
}
如果condition队列不为空,就调用doSignal方法将condition队列头节点插入到CLH队列中。其中transferForSignal()方法在下文讲述
1. 判断是否是独占锁(isHeldExclusively()判断,子类实现),若不是则抛出异常
2. 判断头结点是否为空,若为空不进行操作;否则调用doSignal将该节点置加入CLH队列中
3. 由于插入可能失败,doSignal使用了一个循环,直至插入成功(调用transferForSignal方法)且头结点不为null时结束。插入时,将firstWaiter 指向下一个节点,若下一个节点为空,则代表Condition队列已空,将lastWaiter节点置空。
2.signalAll ()
signalAll ()方法将Condition队列中的所有节点插入到CLH队列中,具体代码如下:
public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignalAll(first);
}
private void doSignalAll(Node first) {
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
transferForSignal(first);
first = next;
} while (first != null);
}
步骤与signal()基本一致,只是在加入队列时从头到尾遍历所有condition节点,将所有节点加入CLH队列中
3.transferForSignal ()
transferForSignal()方法是具体实现将某个Condition节点加入CLH节点,返回boolean值(true:成功;false:失败)在signal()与signalAll()中都需要使用。具体代码如下:
final boolean transferForSignal(Node node) {
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// 将节点node插入到同步队列中,p是原先同步队列尾节点,也是node节点的前一个节点
Node p = enq(node);
int ws = p.waitStatus;
// 如果前一个节点是已取消状态,或者不能将它设置成Node.SIGNAL状态。
// 就说明节点p之后也不会发起唤醒下一个node节点线程的操作,
// 所以这里直接调用 LockSupport.unpark(node.thread)方法,唤醒节点node所在线程
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
步骤描述如下:
本段是AQS所有源码,注释翻译成中文,源码来自https://www.jianshu.com/p/0da2939391cf
package java.util.concurrent.locks;
import sun.misc.Unsafe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer() { }
static final class Node {
// 共享模式的标记
static final Node SHARED = new Node();
// 独占模式的标记
static final Node EXCLUSIVE = null;
// waitStatus变量的值,标志着线程被取消
static final int CANCELLED = 1;
// waitStatus变量的值,标志着后继线程(即队列中此节点之后的节点)需要被阻塞.(用于独占锁)
static final int SIGNAL = -1;
// waitStatus变量的值,标志着线程在Condition条件上等待阻塞.(用于Condition的await等待)
static final int CONDITION = -2;
// waitStatus变量的值,标志着下一个acquireShared方法线程应该被允许。(用于共享锁)
static final int PROPAGATE = -3;
// 标记着当前节点的状态,默认状态是0, 小于0的状态都是有特殊作用,大于0的状态表示已取消
volatile int waitStatus;
// prev和next实现一个双向链表
volatile Node prev;
volatile Node next;
// 该节点拥有的线程
volatile Thread thread;
// 可能有两种作用:1. 表示下一个在Condition条件上等待的节点
// 2. 表示是共享模式或者独占模式,注意第一种情况节点一定是共享模式
Node nextWaiter;
// 是不是共享模式
final boolean isShared() {
return nextWaiter == SHARED;
}
// 返回前一个节点prev,如果为null,则抛出NullPointerException异常
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
// 用于创建链表头head,或者共享模式SHARED
Node() {
}
// 使用在addWaiter方法中
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
// 使用在Condition条件中
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
// CLH队列头
private transient volatile Node head;
// CLH队列尾
private transient volatile Node tail;
// 用来记录当前锁被获取的次数,当state==0,表示还没有被任何线程获取
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
// 采用CAS函数。比较并交换函数,它是原子操作函数;即,通过CAS操作的数据都是以原子方式进行的
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
// Queuing utilities
static final long spinForTimeoutThreshold = 1000L;
// 向队列尾插入新节点,如果队列没有初始化,就先初始化。返回原先的队列尾节点
private Node enq(final Node node) {
for (;;) {
Node t = tail;
// t为null,表示队列为空,先初始化队列
if (t == null) {
// 采用CAS函数即原子操作方式,设置队列头head值。
// 如果成功,再将head值赋值给链表尾tail。如果失败,表示head值已经被其他线程,那么就进入循环下一次
if (compareAndSetHead(new Node()))
tail = head;
} else {
// 新添加的node节点的前一个节点prev指向原来的队列尾tail
node.prev = t;
// 采用CAS函数即原子操作方式,设置新队列尾tail值。
if (compareAndSetTail(t, node)) {
// 设置老的队列尾tail的下一个节点next指向新添加的节点node
t.next = node;
return t;
}
}
}
}
// 通过给定的模式mode(独占或者共享)为当前线程创建新节点,并插入队列中
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方法创建队列,并插入新的节点。
enq(node);
return node;
}
// 重新设置队列头head,它只在acquire系列的方法中调用
private void setHead(Node node) {
head = node;
// 线程也没有意义了,因为该线程已经获取到锁了
node.thread = null;
// 前一个节点已经没有意义了
node.prev = null;
}
// 唤醒node节点的下一个非取消状态的节点所在线程(即waitStatus<=0)
private void unparkSuccessor(Node node) {
// 获取node节点的状态
int ws = node.waitStatus;
// 如果小于0,就将状态重新设置为0,表示这个node节点已经完成了
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
// 下一个节点
Node s = node.next;
// 如果下一个节点为null,或者状态是已取消,那么就要寻找下一个非取消状态的节点
if (s == null || s.waitStatus > 0) {
// 先将s设置为null,s不是非取消状态的节点
s = null;
// 从队列尾向前遍历,直到遍历到node节点
for (Node t = tail; t != null && t != node; t = t.prev)
// 因为是从后向前遍历,所以不断覆盖找到的值,这样才能得到node节点后下一个非取消状态的节点
if (t.waitStatus <= 0)
s = t;
}
// 如果s不为null,表示存在非取消状态的节点。那么调用LockSupport.unpark方法,唤醒这个节点的线程
if (s != null)
LockSupport.unpark(s.thread);
}
// 会唤醒等待共享锁的线程
private void doReleaseShared() {
for (;;) {
// 将同步队列头赋值给节点h
Node h = head;
// 如果节点h不为null,且不等于同步队列尾
if (h != null && h != tail) {
// 得到节点h的状态
int ws = h.waitStatus;
// 如果状态是Node.SIGNAL,就要唤醒节点h后继节点的线程
if (ws == Node.SIGNAL) {
// 将节点h的状态设置成0,如果设置失败,就继续循环,再试一次。
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
// 唤醒节点h后继节点的线程
unparkSuccessor(h);
}
// 如果节点h的状态是0,就设置ws的状态是PROPAGATE。
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
// 如果同步队列头head节点发生改变,继续循环,
// 如果没有改变,就跳出循环
if (h == head)
break;
}
}
// 重新设置CLH队列头,如果CLH队列头的下一个节点为null或者共享模式,
// 那么就要唤醒共享锁上等待的线程
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head;
// 设置新的同步队列头head
setHead(node);
// 如果propagate大于0,
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
// 获取新的CLH队列头的下一个节点s
Node s = node.next;
// 如果节点s是空或者共享模式节点,那么就要唤醒共享锁上等待的线程
if (s == null || s.isShared())
doReleaseShared();
}
}
// 则将node节点的状态设置成CANCELLED,表示node节点所在线程已取消,不需要唤醒了。
private void cancelAcquire(Node node) {
// 如果node为null,就直接返回
if (node == null)
return;
//
node.thread = null;
// 跳过那些已取消的节点,在队列中找到在node节点前面的第一次状态不是已取消的节点
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// 记录pred原来的下一个节点,用于CAS函数更新时使用
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
// 将node节点状态设置为已取消Node.CANCELLED;
node.waitStatus = Node.CANCELLED;
// 如果node节点是队列尾节点,那么就将pred节点设置为新的队列尾节点
if (node == tail && compareAndSetTail(node, pred)) {
// 并且设置pred节点的下一个节点next为null
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
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
}
}
/**
* 根据前一个节点pred的状态,来判断当前线程是否应该被阻塞
* @param pred : node节点的前一个节点
* @param node
* @return 返回true 表示当前线程应该被阻塞,之后应该会调用parkAndCheckInterrupt方法来阻塞当前线程
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
// 如果前一个pred的状态是Node.SIGNAL,那么直接返回true,当前线程应该被阻塞
return true;
if (ws > 0) {
// 如果前一个节点状态是Node.CANCELLED(大于0就是CANCELLED),
// 表示前一个节点所在线程已经被唤醒了,要从CLH队列中移除CANCELLED的节点。
// 所以从pred节点一直向前查找直到找到不是CANCELLED状态的节点,并把它赋值给node.prev,
// 表示node节点的前一个节点已经改变。
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 此时前一个节点pred的状态只能是0或者PROPAGATE,不可能是CONDITION状态
// CONDITION(这个是特殊状态,只在condition列表中节点中存在,CLH队列中不存在这个状态的节点)
// 将前一个节点pred的状态设置成Node.SIGNAL,这样在下一次循环时,就是直接阻塞当前线程
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
/**
* 当前线程发出中断通知
*/
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
/**
* 阻塞当前线程,线程被唤醒后返回当前线程中断状态
*/
private final boolean parkAndCheckInterrupt() {
// 通过LockSupport.park方法,阻塞当前线程
LockSupport.park(this);
// 当前线程被唤醒后,返回当前线程中断状态
return Thread.interrupted();
}
/**
* 想要获取锁的 acquire系列方法,都会这个方法来获取锁
* 循环通过tryAcquire方法不断去获取锁,如果没有获取成功,就有可能调用parkAndCheckInterrupt方法,让当前线程阻塞
* @param node 想要获取锁的节点
* @param arg
* @return 返回true,表示在线程等待的过程中,线程被中断了
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
// 表示线程在等待过程中,是否被中断了
boolean interrupted = false;
// 通过死循环,直到node节点的线程获取到锁,才返回
for (;;) {
// 获取node的前一个节点
final Node p = node.predecessor();
// 如果前一个节点是队列头head,并且尝试获取锁成功
// 那么当前线程就不需要阻塞等待,继续执行
if (p == head && tryAcquire(arg)) {
// 将节点node设置为新的队列头
setHead(node);
// help GC
p.next = null;
// 不需要调用cancelAcquire方法
failed = false;
return interrupted;
}
// 当p节点的状态是Node.SIGNAL时,就会调用parkAndCheckInterrupt方法,阻塞node线程
// node线程被阻塞,有两种方式唤醒,
// 1.是在unparkSuccessor(Node node)方法,会唤醒被阻塞的node线程,返回false
// 2.node线程被调用了interrupt方法,线程被唤醒,返回true
// 在这里只是简单地将interrupted = true,没有跳出for的死循环,继续尝试获取锁
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
// failed为true,表示发生异常,
// 则将node节点的状态设置成CANCELLED,表示node节点所在线程已取消,不需要唤醒了。
if (failed)
cancelAcquire(node);
}
}
/**
* 这个方法与acquireQueued(final Node node, int arg)方法流程几乎一样
* 只不过当parkAndCheckInterrupt返回true时,直接抛出异常。
* @param arg
* @throws InterruptedException
*/
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
// 为当前线程创建节点node,并插入到队列中
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
// 通过死循环,直到node节点的线程获取到锁,或者当前线程有中断请求会抛出中断异常
for (;;) {
final Node p = node.predecessor();
// 如果前一个节点是队列头head,并且尝试获取锁成功
// 将该节点node设置成队列头head
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
// 当p节点的状态是Node.SIGNAL时,就会调用parkAndCheckInterrupt方法,阻塞node线程
// node线程被阻塞,有两种方式唤醒,
// 1.是在unparkSuccessor(Node node)方法,会唤醒被阻塞的node线程,返回false
// 2.node线程被调用了interrupt方法,线程被唤醒,返回true
// 在这里如果parkAndCheckInterrupt返回true,就会抛出InterruptedException异常
// 跳出死循环,方法返回
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
/**
* 尝试在一定的时间nanosTimeout内获取锁,超时了就返回false
*
*/
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
// 计算截止时间
final long deadline = System.nanoTime() + nanosTimeout;
// 为当前线程创建节点node,并插入到队列中
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
// 如果前一个节点是队列头head,并且尝试获取锁成功
// 将该节点node设置成队列头head
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
// 计算剩余时间
nanosTimeout = deadline - System.nanoTime();
// 剩余时间小于等于0,就直接返回false,获取锁失败
if (nanosTimeout <= 0L)
return false;
// 当p节点的状态是Node.SIGNAL时,调用LockSupport.parkNanos阻塞当前线程
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
// 当前线程阻塞nanosTimeout时间
LockSupport.parkNanos(this, nanosTimeout);
// 如果当前线程中断标志位是true,抛出InterruptedException异常
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
// failed为true,表示发生异常,
// 则将node节点的状态设置成CANCELLED,表示node节点所在线程已取消,不需要唤醒了
if (failed)
cancelAcquire(node);
}
}
/**
* 获取共享锁,获取失败,则会阻塞当前线程,直到获取共享锁返回
* @param arg the acquire argument
*/
private void doAcquireShared(int arg) {
// 为当前线程创建共享锁节点node
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
// 如果节点node前一个节点是同步队列头节点。就会调用tryAcquireShared方法尝试获取共享锁
if (p == head) {
int r = tryAcquireShared(arg);
// 如果返回值大于0,表示获取共享锁成功
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
// 如果节点p的状态是Node.SIGNAL,就是调用parkAndCheckInterrupt方法阻塞当前线程
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
// failed为true,表示发生异常,
// 则将node节点的状态设置成CANCELLED,表示node节点所在线程已取消,不需要唤醒了
if (failed)
cancelAcquire(node);
}
}
/**
* Acquires in shared interruptible mode.
* @param arg the acquire argument
*/
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 {
// failed为true,表示发生异常,
// 则将node节点的状态设置成CANCELLED,表示node节点所在线程已取消,不需要唤醒了
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);
}
}
// Main exported methods
// 尝试去获取独占锁,立即返回。如果返回true表示获取锁成功。
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
// 尝试去释放当前线程持有的独占锁,立即返回。如果返回true表示释放锁成功
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
// 尝试去获取共享锁,立即返回。返回值大于等于0,表示获取共享锁成功
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
// 尝试去释放共享锁
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
/**
* 获取独占锁。如果没有获取到,线程就会阻塞等待,直到获取锁。不会响应中断异常
* @param arg
*/
public final void acquire(int arg) {
// 1. 先调用tryAcquire方法,尝试获取独占锁,返回true,表示获取到锁,不需要执行acquireQueued方法。
// 2. 调用acquireQueued方法,先调用addWaiter方法为当前线程创建一个节点node,并插入队列中,
// 然后调用acquireQueued方法去获取锁,如果不成功,就会让当前线程阻塞,当锁释放时才会被唤醒。
// acquireQueued方法返回值表示在线程等待过程中,是否有另一个线程调用该线程的interrupt方法,发起中断。
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// public final void acquire(int arg) {
// // 1.先调用tryAcquire方法,尝试获取独占锁,返回true则直接返回
// if (tryAcquire(arg)) return;
// // 2. 调用addWaiter方法为当前线程创建一个节点node,并插入队列中
// Node node = addWaiter(Node.EXCLUSIVE);
// // 调用acquireQueued方法去获取锁,
// // acquireQueued方法返回值表示在线程等待过程中,是否有另一个线程调用该线程的interrupt方法,发起中断。
// boolean interrupted = acquireQueued(node, arg);
// // 如果interrupted为true,则当前线程要发起中断请求
// if (interrupted) {
// selfInterrupt();
// }
// }
/**
* 获取独占锁。如果没有获取到,线程就会阻塞等待,直到获取锁。如果有中断请求就会产生中断异常
* @param arg
*/
public final void acquireInterruptibly(int arg)
throws InterruptedException {
// 如果当前线程中断标志位是true,那么直接抛出中断异常
if (Thread.interrupted())
throw new InterruptedException();
// 先调用tryAcquire方法,尝试获取独占锁,返回true,表示获取到锁,不需要执行doAcquireInterruptibly方法。
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
/**
* 尝试在一定时间内获取独占锁。如果有中断请求就会产生中断异常。
* 返回true,表示获取锁成功
*/
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
// 如果当前线程中断标志位是true,那么直接抛出中断异常
if (Thread.interrupted())
throw new InterruptedException();
// 先调用tryAcquire方法,尝试获取独占锁,返回true,表示获取到锁。
// 否则调用doAcquireNanos方法获取锁
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
// 在独占锁模式下,释放锁的操作
public final boolean release(int arg) {
// 调用tryRelease方法,尝试去释放锁,由子类具体实现
if (tryRelease(arg)) {
Node h = head;
// 如果队列头节点的状态不是0,那么队列中就可能存在需要唤醒的等待节点。
// 还记得我们在acquireQueued(final Node node, int arg)获取锁的方法中,如果节点node没有获取到锁,
// 那么我们会将节点node的前一个节点状态设置为Node.SIGNAL,然后调用parkAndCheckInterrupt方法
// 将节点node所在线程阻塞。
// 在这里就是通过unparkSuccessor方法,进而调用LockSupport.unpark(s.thread)方法,唤醒被阻塞的线程
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
// 获取共享锁
public final void acquireShared(int arg) {
// 尝试去获取共享锁,如果返回值小于0表示获取共享锁失败
if (tryAcquireShared(arg) < 0)
// 调用doAcquireShared方法去获取共享锁
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;
}
// Queue inspection methods
public final boolean hasQueuedThreads() {
return head != tail;
}
public final boolean hasContended() {
return head != null;
}
public final Thread getFirstQueuedThread() {
// handle only fast path, else relay
return (head == tail) ? null : fullGetFirstQueuedThread();
}
/**
* Version of getFirstQueuedThread called when fastpath fails
*/
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;
}
// 返回false表示队列为null,或者当前线程节点在是队列头的下一个节点。
// 返回true表示有一个线程节点在当前线程节点之前
public final boolean hasQueuedPredecessors() {
Node t = tail;
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
// Instrumentation and monitoring methods
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 getQueuedThreads() {
ArrayList list = new ArrayList();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
}
public final Collection getExclusiveQueuedThreads() {
ArrayList list = new ArrayList();
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 getSharedQueuedThreads() {
ArrayList list = new ArrayList();
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]";
}
// Internal support methods for Conditions
// 节点node是不是在CLH队列中
final boolean isOnSyncQueue(Node node) {
// 如果node的状态是Node.CONDITION,或者node没有前一个节点prev,
// 那么返回false,节点node不在同步队列中
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
// 如果node有下一个节点next,那么它一定在同步队列中
if (node.next != null) // If has successor, it must be on queue
return true;
// 从同步队列中查找节点node
return findNodeFromTail(node);
}
// 在同步队列中从后向前查找节点node,如果找到返回true,否则返回false
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
// 返回true表示节点node插入到同步队列中,返回false表示节点node没有插入到同步队列中
final boolean transferForSignal(Node node) {
// 如果节点node的状态不是Node.CONDITION,或者更新状态失败,
// 说明该node节点已经插入到同步队列中,所以直接返回false
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
// 将节点node插入到同步队列中,p是原先同步队列尾节点,也是node节点的前一个节点
Node p = enq(node);
int ws = p.waitStatus;
// 如果前一个节点是已取消状态,或者不能将它设置成Node.SIGNAL状态。
// 就说明节点p之后也不会发起唤醒下一个node节点线程的操作,
// 所以这里直接调用 LockSupport.unpark(node.thread)方法,唤醒节点node所在线程
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
// 等待节点node存放到同步队列中,如果是当前线程插入的,返回true,如果是另一个线程插入的,返回false。
final boolean transferAfterCancelledWait(Node node) {
// 当节点node状态还是Node.CONDITION,改变它的状态是0,然后插入到同步队列中。
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
// 如果节点node不在同步队列中,当前线程让出执行权
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
/**
* 释放当前线程占有的锁,并唤醒CLH队列一个等待线程
* 如果失败就抛出异常,设置node节点的状态是Node.CANCELLED
* @return
*/
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;
}
}
// Instrumentation methods for conditions
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 getWaitingThreads(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitingThreads();
}
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
/** Condition队列头. */
private transient Node firstWaiter;
/** Condition队列尾. */
private transient Node lastWaiter;
/**
* Creates a new {@code ConditionObject} instance.
*/
public ConditionObject() { }
// Internal methods
/**
* 为当前线程创建新的Node节点,并且将这个节点插入到Condition队列中了
* @return its new wait node
*/
private Node addConditionWaiter() {
Node t = lastWaiter;
// 如果Condition队列尾节点的状态不是Node.CONDITION
if (t != null && t.waitStatus != Node.CONDITION) {
// 清除Condition队列中,状态不是Node.CONDITION的节点,
// 并且可能会重新设置firstWaiter和lastWaiter
unlinkCancelledWaiters();
// 重新将Condition队列尾赋值给t
t = lastWaiter;
}
// 为当前线程创建一个状态为Node.CONDITION的节点
Node node = new Node(Thread.currentThread(), Node.CONDITION);
// 如果t为null,表示Condition队列为空,将node节点赋值给链表头
if (t == null)
firstWaiter = node;
else
// 将新节点node插入到Condition队列尾
t.nextWaiter = node;
// 将新节点node设置为新的Condition队列尾
lastWaiter = node;
return node;
}
// 将Condition队列中的first节点插入到CLH队列中
private void doSignal(Node first) {
do {
// 原先的Condition队列头节点取消,所以重新赋值Condition队列头节点
// 如果新的Condition队列头节点为null,表示Condition队列为空了
// ,所以也要设置Condition队列尾lastWaiter为null
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
// 取消first节点nextWaiter引用
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
/**
* 将condition队列中所有的节点都插入到同步队列中
* @param first condition队列头节点
*/
private void doSignalAll(Node first) {
// 表示将condition队列设置为空
lastWaiter = firstWaiter = null;
do {
// 得到condition队列的下一个节点
Node next = first.nextWaiter;
first.nextWaiter = null;
// 将节点first插入到同步队列中
transferForSignal(first);
first = next;
// 循环遍历condition队列中所有的节点
} while (first != null);
}
// 清除Condition队列中状态不是Node.CONDITION的节点
private void unlinkCancelledWaiters() {
// condition队列头赋值给t
Node t = firstWaiter;
// 这个trail节点,只是起辅助作用
Node trail = null;
while (t != null) {
//得到下一个节点next。当节点是condition时候,nextWaiter表示condition队列的下一个节点
Node next = t.nextWaiter;
// 如果节点t的状态不是CONDITION,那么该节点就要从condition队列中移除
if (t.waitStatus != Node.CONDITION) {
// 将节点t的nextWaiter设置为null
t.nextWaiter = null;
// 如果trail为null,表示原先的condition队列头节点实效,需要设置新的condition队列头
if (trail == null)
firstWaiter = next;
else
// 将节点t从condition队列中移除,因为改变了引用的指向,从condition队列中已经找不到节点t了
trail.nextWaiter = next;
// 如果next为null,表示原先的condition队列尾节点也实效,重新设置队列尾节点
if (next == null)
lastWaiter = trail;
}
else
// 遍历到的有效节点
trail = t;
// 将next赋值给t,遍历完整个condition队列
t = next;
}
}
// public methods
// 如果condition队列不为空,将condition队列头节点插入到同步队列中
public final void signal() {
// 如果当前线程不是独占锁线程,就抛出IllegalMonitorStateException异常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
// 将Condition队列头赋值给节点first
Node first = firstWaiter;
if (first != null)
// 将Condition队列中的first节点插入到CLH队列中
doSignal(first);
}
// 将condition队列中所有的节点都插入到同步队列中
public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignalAll(first);
}
// 让当前持有锁的线程阻塞等待,并释放锁。如果线程等待期间发出中断请求,不会产生中断异常
public final void awaitUninterruptibly() {
// 为当前线程创建新的Node节点,并且将这个节点插入到Condition队列中了
Node node = addConditionWaiter();
// 释放当前线程占有的锁,并唤醒其他线程
int savedState = fullyRelease(node);
boolean interrupted = false;
// 如果节点node不在同步队列中(注意不是Condition队列),就阻塞当前线程
while (!isOnSyncQueue(node)) {
// 阻塞当前线程
LockSupport.park(this);
if (Thread.interrupted())
interrupted = true;
}
// 如果节点node已经在同步队列中了,获取同步锁,只有得到锁才能继续执行,否则线程继续阻塞等待
if (acquireQueued(node, savedState) || interrupted)
selfInterrupt();
}
/** Mode meaning to reinterrupt on exit from wait */
private static final int REINTERRUPT = 1;
/** Mode meaning to throw InterruptedException on exit from wait */
private static final int THROW_IE = -1;
/**
* 如果线程没有发起了中断请求,返回0.
* 如果线程发起了中断请求,且中断请求在signalled(即调用signal或signalAll)之前返回THROW_IE
* 中断请求在signalled之后返回REINTERRUPT
*/
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}
/**
* 如果interruptMode是THROW_IE,就抛出InterruptedException异常
* 如果interruptMode是REINTERRUPT,则当前线程再发出中断请求
* 否则就什么都不做
*/
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
/**
* 让当前持有锁的线程阻塞等待,并释放锁。如果有中断请求,则抛出InterruptedException异常
* @throws InterruptedException
*/
public final void await() throws InterruptedException {
// 如果当前线程中断标志位是true,就抛出InterruptedException异常
if (Thread.interrupted())
throw new InterruptedException();
// 为当前线程创建新的Node节点,并且将这个节点插入到Condition队列中了
Node node = addConditionWaiter();
// 释放当前线程占有的锁,并唤醒CLH队列一个等待线程
int savedState = fullyRelease(node);
int interruptMode = 0;
// 如果节点node不在同步队列中(注意不是Condition队列)
while (!isOnSyncQueue(node)) {
// 阻塞当前线程,那么怎么唤醒这个线程呢?
// 首先我们必须调用signal或者signalAll将这个节点node加入到同步队列。
// 只有这样unparkSuccessor(Node node)方法,才有可能唤醒被阻塞的线程
LockSupport.park(this);
// 如果当前线程产生中断请求,就跳出循环
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// 如果节点node已经在同步队列中了,获取同步锁,只有得到锁才能继续执行,否则线程继续阻塞等待
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
// 清除Condition队列中状态不是Node.CONDITION的节点
if (node.nextWaiter != null)
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;
// 清除Condition队列中状态不是Node.CONDITION的节点
if (node.nextWaiter != null)
unlinkCancelledWaiters();
// 是否要抛出异常,或者发出中断请求
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return !timedout;
}
/**
* 返回true:表示这个condition对象是由sync对象创建的。
*/
final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
return sync == AbstractQueuedSynchronizer.this;
}
/**
* 这个condition对象上是否有等待线程,即condition队列不为空,且有一个节点的状态是 Node.CONDITION
*/
protected final boolean hasWaiters() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
// 遍历condition队列
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
return true;
}
return false;
}
/**
* 返回condition对象上等待线程的个数,即遍历condition队列,计算节点的状态是Node.CONDITION的个数
*/
protected final int getWaitQueueLength() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int n = 0;
// 遍历condition队列
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
// 计算节点的状态是Node.CONDITION的个数
if (w.waitStatus == Node.CONDITION)
++n;
}
return n;
}
/**
* 返回condition对象上等待线程的集合。
*/
protected final Collection getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList list = new ArrayList();
// 遍历condition队列
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
// 当节点的状态是Node.CONDITION,将节点的线程添加到list集合中
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
if (t != null)
list.add(t);
}
}
return list;
}
}
// 支持compareAndSet操作
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); }
}
/**
* 通过CAS函数设置head值,仅仅在enq方法中调用
*/
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
/**
* 通过CAS函数设置tail值,仅仅在enq方法中调用
*/
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
/**
* 通过CAS函数设置node对象的waitStatus值
*/
private static final boolean compareAndSetWaitStatus(Node node,int expect,int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset,expect, update);
}
/**
* 通过CAS函数设置node对象的next值
*/
private static final boolean compareAndSetNext(Node node,
Node expect,
Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
}