源码解读的注释都在代码中,有些重复的代码没有注释,如若有哪些地方我理解错了欢迎评论区留言或者私信我指正,成长的路上相互学习共同进步。
AQS原理
- Abstract : 在AbstractQueuedSynchronizer 中不知道具体怎么上锁。所以使用模板方法设计模式,暴露出上锁逻辑
- Queue:线程阻塞队列
- Synchronizer:同步
- CAS+state 完成多线程抢锁逻辑
- Queue 完成抢不到锁的线程排队(同步线程)
- 如果是ReentrantLock创建了多个condition,那么这儿还有多个条件等待队列
import java.io.Serializable;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.*;
import java.util.concurrent.locks.AbstractOwnableSynchronizer;
/**
* @author hejs
* @version 1.0
* @createDate 2022年02月23日 16:00
* @since JDK1.8
*/
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements Serializable {
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer() { }
static final class Node {
//线程共享锁时的标志
static final AbstractQueuedSynchronizer.Node SHARED = new AbstractQueuedSynchronizer.Node();
//线程独占锁的标志
static final AbstractQueuedSynchronizer.Node EXCLUSIVE = null;
//取消节点,唯一大于0的等待状态
static final int CANCELLED = 1;
//上一个节点是SIGNAL,当前节点才有可能被上一个节点唤醒。
static final int SIGNAL = -1;
//表示该线程在condition队列中阻塞(Condition有使用)
static final int CONDITION = -2;
//表示该线程以及后续线程进行无条件传播(CountDownLatch中有使用)共享模式下, PROPAGATE 状态的线程处于可运行状态
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile AbstractQueuedSynchronizer.Node prev;
volatile AbstractQueuedSynchronizer.Node next;
volatile Thread thread;
/**
* 下一个等待者,注意与尾结点tail和next区分开
*/
AbstractQueuedSynchronizer.Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
/**
* 获取前续节点,如果前续节点为空,这抛异常
* @return
*/
final AbstractQueuedSynchronizer.Node predecessor() {
AbstractQueuedSynchronizer.Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() {}
/**
* 把当前线程封装到节点中
* @param nextWaiter
*/
Node(AbstractQueuedSynchronizer.Node nextWaiter) {
this.nextWaiter = nextWaiter;
THREAD.set(this, Thread.currentThread());
}
Node(int waitStatus) {
WAITSTATUS.set(this, waitStatus);
THREAD.set(this, Thread.currentThread());
}
/** CASes waitStatus field. */
final boolean compareAndSetWaitStatus(int expect, int update) {
return WAITSTATUS.compareAndSet(this, expect, update);
}
/** CASes next field. */
final boolean compareAndSetNext(AbstractQueuedSynchronizer.Node expect, AbstractQueuedSynchronizer.Node update) {
return NEXT.compareAndSet(this, expect, update);
}
final void setPrevRelaxed(AbstractQueuedSynchronizer.Node p) {
PREV.set(this, p);
}
// VarHandle mechanics
//这几个变量对应 next prev thread waitstatus变量
//主要作用是使用这个类型的变量,可以使得操作具有原子性,保障多线程下的线程安全
//用这几个变量的操作结果最终也是对next prev thread waitstatus变量的操作
//因为指向的是同一块内存
private static final VarHandle NEXT;
private static final VarHandle PREV;
private static final VarHandle THREAD;
private static final VarHandle WAITSTATUS;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
NEXT = l.findVarHandle(AbstractQueuedSynchronizer.Node.class, "next", AbstractQueuedSynchronizer.Node.class);
PREV = l.findVarHandle(AbstractQueuedSynchronizer.Node.class, "prev", AbstractQueuedSynchronizer.Node.class);
THREAD = l.findVarHandle(AbstractQueuedSynchronizer.Node.class, "thread", Thread.class);
WAITSTATUS = l.findVarHandle(AbstractQueuedSynchronizer.Node.class, "waitStatus", int.class);
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}
}
private transient volatile AbstractQueuedSynchronizer.Node head;
private transient volatile AbstractQueuedSynchronizer.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 STATE.compareAndSet(this, expect, update);
}
static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
/**
*往同步队列中添加线程节点 全路径 + 优化前置方式
* @param node
* @return
*/
private AbstractQueuedSynchronizer.Node enq(AbstractQueuedSynchronizer.Node node) {
for (;;) {
//创建尾结点临时快照
AbstractQueuedSynchronizer.Node oldTail = tail;
//判断队尾是否有节点,如果同步队列被初始化过,那么队尾肯定不为空
//如果同步队列里只有一个线程节点,那么第头结点和尾结点都指向这个节点
//如果同步队列被初始化过,即队列中至少有一个线程节点在排队,那么把当前线程节点排在其后
if (oldTail != null) {
//当前线程节点进行入队操作,先把线程节点pre指针直接指向尾节点(可能多个线程都在进行)
node.setPrevRelaxed(oldTail);
//cas将尾结点更新为当前线程构成的node节点(只有一个成功,没成功的重新进入循环处理)
if (compareAndSetTail(oldTail, node)) {
//尾结点更新成功后,最后才更新原来的尾结点的next指正指向node节点
// (由于if语句中的cas已经保证只有一个线程成功,故这里是线程安全的)
oldTail.next = node;
//添加成功后返回的是原来尾结点(这里是和addWork方法的唯一差别)
return oldTail;
}
} else {
//如果同步队列未被初始化,那么进行初始化,再进入循环进行入队操作
//初始化操作就是创建一个节点,但是线程为null
initializeSyncQueue();
}
}
}
/**
*往队列中添加等待者(当前线程构成的线程节点)
* @param mode
* @return
*/
private AbstractQueuedSynchronizer.Node addWaiter(AbstractQueuedSynchronizer.Node mode) {
//新建node线程节点,并将当前线程封装到该节点中
AbstractQueuedSynchronizer.Node node = new AbstractQueuedSynchronizer.Node(mode);
for (;;) {
//建立尾节点临时变量(尾节点快照)
AbstractQueuedSynchronizer.Node oldTail = tail;
//判断队尾是否有节点,如果同步队列被初始化过,那么队尾肯定不为空
//如果同步队列里只有一个线程节点,那么第头结点和尾结点都指向这个节点
//如果同步队列被初始化过,即队列中至少有一个线程节点在排队,那么把当前线程节点排在其后
if (oldTail != null) {
//当前线程节点进行入队操作,先把线程节点pre指针直接指向尾节点(可能多个线程都在进行)
node.setPrevRelaxed(oldTail);
//cas将尾结点更新为当前线程构成的node节点(只有一个成功,没成功的重新进入循环处理)
if (compareAndSetTail(oldTail, node)) {
//尾结点更新成功后,最后才更新原来的尾结点的next指正指向node节点
// (由于if语句中的cas已经保证只有一个线程成功,故这里是线程安全的)
oldTail.next = node;
//入队成功,返回新加的节点(这里是和enq的唯一差别)
return node;
}
//如果同步队列未被初始化,那么进行初始化,再进入循环进行入队操作
//初始化操作就是创建一个节点,但是线程为null
} else {
initializeSyncQueue();
}
}
}
/**
* 设置节点为头结点,前续节点和thread为null
* @param node
*/
private void setHead(AbstractQueuedSynchronizer.Node node) {
head = node;
node.thread = null;
node.prev = null;
}
/**
*唤醒node节点后的第一个有效后继节点。从node节点往后找到第一个有效地节点,唤醒即可。
* node后的第一个等待节点被取消变成无效节点或者next指针为null,
* 那么就从尾部查到node后的第一等待节点
* @param node
*/
private void unparkSuccessor(AbstractQueuedSynchronizer.Node node) {
//获取node节点的等待状态临时快照
int ws = node.waitStatus;
// 开始唤醒后继节点,当前头节点,且ws=SINGAL,CAS将其变为0,代表了我当前已经响应了这一次的唤醒操作
//node节点为有效节点
if (ws < 0)
//设置节点的等待状态为默认状态
node.compareAndSetWaitStatus(ws, 0);
//获取第一个等待节点的临时快照
AbstractQueuedSynchronizer.Node s = node.next;
// 注意这里为什么这里有可能为空?因为我们首先更新的是tail引用,然后再是旧的tail.next所以有可能这一瞬间为空
//如果第一个等待节点为空,或者等待节点等待状态为取消状态,即无效节点
if (s == null || s.waitStatus > 0) {
//置空用于记录尾遍历找到的第一个有效等待节点
s = null;
// tail引用一定是最新的引用,那么从后往前找到 第一个(node节点的后继的第一个) 有效节点
for (AbstractQueuedSynchronizer.Node p = tail; p != node && p != null; p = p.prev)
if (p.waitStatus <= 0)
s = p;
}
// 找到node节点后的第一个有效节点,唤醒该节点
if (s != null)
LockSupport.unpark(s.thread);
}
/**
* 释放共享锁,唤醒
*/
private void doReleaseShared() {
for (;;) {
//获取头结点临时快照
AbstractQueuedSynchronizer.Node h = head;
//头节点不为空-->同步队列有等待节点,头节点和尾节点不是同一节点,等待队列中不止一个等待节点
//在这个if语句中,如果唤醒失败,那么就进入下次循环,如果成功就判断一下头结点变了吗
// (变了说明有其他线程也在执行这个操作)那么我就不操作了,结束循环
if (h != null && h != tail) {
int ws = h.waitStatus;
//头节点的等待状态为唤醒后续节点状态(SIGNAL)
if (ws == AbstractQueuedSynchronizer.Node.SIGNAL) {
//cas修改等待状态为0,修改成功则释放该节点并唤醒后面的有效节点
//修改失败说明刚才有其他线程已经修改过并唤醒了其第一个后续节点,重新进入循环获取最新头结点执行一遍
if (!h.compareAndSetWaitStatus(AbstractQueuedSynchronizer.Node.SIGNAL, 0))
continue; // loop to recheck cases
//修改成功,那么唤醒node节点后的第一个有效后继节点。从node节点往后找到第一个有效地节点,唤醒即可。
unparkSuccessor(h);
}
//如果等待状态为0,说明可能已经唤醒后续节点了,将其改为唤醒传播状态
//如果修改失败,则进入下次循环,获取新的头结点执行一遍唤醒下一节点操作
else if (ws == 0 &&
!h.compareAndSetWaitStatus(0, AbstractQueuedSynchronizer.Node.PROPAGATE))
continue; // loop on failed CAS
}
//头结点已经变了,结束循环
if (h == head) // loop if head changed
break;
}
}
/**
* 面试重点,难点:
* 用于更新头结点,并且唤醒后继共享节点
* @param node
* @param propagate 剩余信号量(semaphore中)
*/
private void setHeadAndPropagate(AbstractQueuedSynchronizer.Node node, int propagate) {
//获取头结点临时快照
AbstractQueuedSynchronizer.Node h = head; // Record old head for check below
//设置头结点为node节点
setHead(node);
// 1、propagate > 0 -->信号量还有多余的,那么直接唤醒。eg:A:2 head->B-C
// 2、h.waitStatus < 0 -->表明头结点的后续节点等待唤醒 那么直接唤醒
//3、 (h = head) == null || h.waitStatus < 0) --> 获取最新头节点,如果头节点状态为等待唤醒状态 表明必须唤醒后继节点 那么直接唤醒
//4、为什么重复判断h == null 和h.waitStatus? 获取最新的头节点,执行前面的判断可能头节点已经换新的节点了
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
//获取新头结点的后续节点临时快照
AbstractQueuedSynchronizer.Node s = node.next;
//新头结点后一节点有等待节点,或者是后一节点是共享锁节点,那么
if (s == null || s.isShared())
doReleaseShared();
}
}
// Utilities for various versions of acquire
/**
* 取消node节点
* 并将node后的节点连在node前的有效节点上,相当于将node节点砍下来,并连上前续和后继
* @param node
*/
private void cancelAcquire(AbstractQueuedSynchronizer.Node node) {
// Ignore if node doesn't exist
//如果node节点不存在,直接结束该方法。
if (node == null)
return;
//将取消节点的thread释放掉,帮助GC
node.thread = null;
// 获取被取消节点的前续节点
AbstractQueuedSynchronizer.Node pred = node.prev;
//while循环找到node节点的有效前续节点
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
//跳出循环即找到一个没有被取消的节点
//获取while循环找到的node节点之前的第一个有效节点的下一节点快照
AbstractQueuedSynchronizer.Node predNext = pred.next;
//设置node节点的等待状态为取消状态
node.waitStatus = AbstractQueuedSynchronizer.Node.CANCELLED;
// 如果取消的节点是尾结点,则将尾结点CAS为当前找到的那个未被取消的节点
if (node == tail && compareAndSetTail(node, pred)) {
//设置成功后并把当前未被取消的节点指向后继节点的引用置为空(即新尾结点的next引用置为空),完成node节点的出队
pred.compareAndSetNext(predNext, null);
} else {//到这儿,1、被取消的节点不是尾结点
// 2、设置尾结点失败
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
//找到的当前未取消的节点不是头结点,且(等待状态为SIGNAL或者(非取消状态-->设置为SIGNAL成功)并且当前节点的线程不为空
if (pred != head &&
((ws = pred.waitStatus) == AbstractQueuedSynchronizer.Node.SIGNAL ||
(ws <= 0 && pred.compareAndSetWaitStatus(ws, AbstractQueuedSynchronizer.Node.SIGNAL))) &&
pred.thread != null) {
//if总结:找到的节点不是头结点且包含的线程存在,并设置等待状态为SIGNAL
AbstractQueuedSynchronizer.Node next = node.next;
if (next != null && next.waitStatus <= 0)//将取消的节点后的节点接到找到的未取消的节点的后继引用上
pred.compareAndSetNext(predNext, next);
} else {
//是头结点,释放锁
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
/**
*设置新节点的前驱节点的等待状态位SIGNAL,
* 以至于后面使用时能够唤醒该新加入的节点
* 这里还处理了丢弃队列中已插入但却被取消的节点
* 取消的节点可能是超时等待,打断等情况
* @param pred
* @param node
* @return
* shouldParkAfterFailedAcquire-->方法意思为:获取锁失败后应不应该阻塞?
*/
private static boolean shouldParkAfterFailedAcquire(AbstractQueuedSynchronizer.Node
pred, AbstractQueuedSynchronizer.Node node) {
int ws = pred.waitStatus;
//前续节点是SIGNAL等待状态,自己可以安心阻塞,反正前续节点会唤醒我
if (ws == AbstractQueuedSynchronizer.Node.SIGNAL)//前置节点如果是SIGNAL,SIGNAL表示唤醒后一节点
//返回true表示告诉线程,你安心去阻塞睡觉吧,我会叫醒你的
return true;
if (ws > 0) {//这里大于0表示node的前续节点已经被取消掉了,应该跳过该节点,直到找到一个有效的前续节点
//这个循环在清理同步队列中的无效节点(被取消的节点)这些无效节点将在同步队列中消失
do {
//node为加入的新节点,pre为前续节点
// 1、pred = pred.prev;:前续节点的引用指向前续节点的再前续节点(pre引用直接跳过失效的node的前续节点)
// 2、node指向前续节点的引用(指针)指向失效节点的前续节点(即跳过取消的节点)
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);//node节点这样跳过失效节点直至找到有效的节点为止
pred.next = node;//当前找到的有效节点指向后续节点指针直接指向刚插入的新节点
} else {
//前续节点就是有效节点
//CAS使得新节点的前驱节点的等待状态改为SiGNAL,以至于后面能够唤醒新节点
pred.compareAndSetWaitStatus(ws, AbstractQueuedSynchronizer.Node.SIGNAL);
}
//如果前续节点是取消的节点,那么返回false,不能park睡觉,睡了没人叫你
return false;
}
/**
* 中断当前线程
*/
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
/**
* 阻塞当前线程并返回打断标志位
* @return
*/
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);//阻塞当前线程,被唤醒的线程节点将从这儿开始执行
return Thread.interrupted();//返回打断标志位并复位
}
/**
*这个方法名和其意思不太一致,入队的操作应该是addWaiter()方法
* 这里应该是判断刚进入同步队列的node节点尝试获取锁和是否进行阻塞(park)
* @param node
* @param arg
* @return
*/
final boolean acquireQueued(final AbstractQueuedSynchronizer.Node node, int arg) {
boolean interrupted = false;//中断标记
try {
for (;;) {
//获取前续节点做临时快照
final AbstractQueuedSynchronizer.Node p = node.predecessor();
//如果前续节点就是头节点,(可能前续节点这时刚好释放锁)所以让当前线程去尝试获取锁
//调用acquireQueued()方法的acquire()中已经调用过tryAcquire(arg)了,失败才调用acquireQueued()入队的,这里为啥还要判断?
//当我是第一个等待节点入队后,我得看看前面的节点搞完没有,
// 搞完了就该我加锁处理了,我就不用park了,否者我park了,我还得唤醒一下,这不浪费时间嘛
if (p == head && tryAcquire(arg)) {
setHead(node);//获取锁成功把该节点设置为头节点
p.next = null; // help GC,也是出队的操作,删除链表前后关联关系
//返回方法中定义的中断标记
return interrupted;
}
//1、前置节点是头节点但没获取锁,2、前置节点不是头节点
//如果是这两种情况,你就在同步队列里park吧,等待我唤醒你,别瞎转悠浪费cpu
//但是在park前先改变前面节点的等待状态位为SIGNAL,以便后面唤醒自己,
// 相当于给前面的兄弟打声招呼,哥们儿你结束后记得叫我哈,我睡会儿
if (shouldParkAfterFailedAcquire(p, node))
//parkAndCheckInterrupt()阻塞(park)当前线程并返回当前方法的中断标记
//将返回的打断标志位与false进行或运算,也就是如果线程被打断过,那么这个值就是true,否者为false
interrupted |= parkAndCheckInterrupt();
//shouldParkAfterFailedAcquire()这里如果返回false,
// 那么进入循环,此时同步队列中已经清楚了被取消的节点,会再次执行获取锁和是否阻塞操作
}
} catch (Throwable t) {
//捕获异常,取消节点,由于前面设置了这个节点为tail,
// 所以在多线程下可能该节点后已经接了其他线程节点了,
// 取消的同时,得将node后一个节点的pre引用指向node前面的有效节点上,
// 且该有效节点的next指向node后的这个节点
cancelAcquire(node);
//如果线程被中断,在加入队列并阻塞后,如果被阻塞这段时间被打断过,那么唤醒后便会自我打断
if (interrupted)
//当前线程自我打断一下
selfInterrupt();
throw t;
}
}
/**
* 带抛出异常的设置前序节点的等待状态,如果前序节点被打断了则取消该节点
* @param arg
* @throws InterruptedException
*/
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
//往队列中加入刚才尝试获取锁失败的线程,以独占锁的方式
final AbstractQueuedSynchronizer.Node node = addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE);
try {
for (;;) {
//获取node的前续节点快照
final AbstractQueuedSynchronizer.Node p = node.predecessor();
//前序节点如果是头节点,再次尝试获取锁,成功便将当前节点设置为头结点
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
//返回true,表示获取锁成功
return;
}
//前序节点不是头节点或者是头结点但是加锁失败(走到这个if的情况)
//改变前面节点的等待状态为SIGNAL,表示前面节点释放锁时唤醒我
if (shouldParkAfterFailedAcquire(p, node) &&
//阻塞当前线程,并检查打断标志位
parkAndCheckInterrupt())
//if总结:改变前序节点为SIGNAL成功,自己去安心阻塞去了,被唤醒时,返回这段时间有没有被打断过,
// 如果打断过,直接抛下面异常
throw new InterruptedException();
}
} catch (Throwable t) {
//捕获被唤醒的线程被中断的打断异常,取消该线程节点后,并向上抛异常
cancelAcquire(node);
throw t;
}
}
/**
*带等待时间的获取锁
* 即在这个时间内获取锁失败就抛异常,不再获取等了
* @param arg
* @param nanosTimeout
* @return
* @throws InterruptedException
*/
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
//等待时间小于等于0,直接加锁失败,返回false
if (nanosTimeout <= 0L)
return false;
//获取最晚获取锁的时间截点
final long deadline = System.nanoTime() + nanosTimeout;
//将当前线程加入到等待队列
final AbstractQueuedSynchronizer.Node node = addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE);
try {
for (;;) {
//获取新加入到等待队列的前续节点
final AbstractQueuedSynchronizer.Node p = node.predecessor();
//如果前续节点为头结点那么尝试一下获取锁
if (p == head && tryAcquire(arg)) {
//获取锁成功便将该新加入的节点设置为头结点
setHead(node);
p.next = null; // help GC
return true;
}
//验证获取锁有没有超时,如果超时便取消该节点
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L) {
cancelAcquire(node);
return false;//并返回,结束该线程加锁
}
//还未超时并且还未获取锁成功(执行到这里)
//设置前续有效节点的等待位为SIGNAL并且剩余加锁等待时间大于1秒
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);//阻塞该线程nanoTimeout时间
if (Thread.interrupted())//如果线程被打断过,直接抛异常
throw new InterruptedException();
}
} catch (Throwable t) {
//捕获抛出的打断异常,并取消节点后继续往上抛
cancelAcquire(node);
throw t;
}
}
/**
* 该获取锁是获取共享锁,即读锁
* @param arg
*/
private void doAcquireShared(int arg) {
//添加到同步队列,以共享锁的方式
final AbstractQueuedSynchronizer.Node node = addWaiter(AbstractQueuedSynchronizer.Node.SHARED);
boolean interrupted = false;
try {
for (;;) {
//获取新加入队列的前续节点(快照)
final AbstractQueuedSynchronizer.Node p = node.predecessor();
if (p == head) {//如果新加入节点前续节点是头结点便尝试获取共享锁,获取共享锁的逻辑由子类实现
int r = tryAcquireShared(arg);
if (r >= 0) {
// 如果获取锁成功,尝试唤醒后面的共享节点(因为共享锁是可以多线程同时获取)
setHeadAndPropagate(node, r);// 将当前获取锁的共享节点更新头节点,然后唤醒后继节点
p.next = null; // help GC,也是p节点移出队列
//获取共享锁成功,退出循环
return;
}
}
//设置新节点的前驱节点的等待状态位SIGNAL,中间丢弃取消的节点
if (shouldParkAfterFailedAcquire(p, node))
interrupted |= parkAndCheckInterrupt();//阻塞当前线程,被唤醒后返回打断标志位
}
} catch (Throwable t) {
cancelAcquire(node);
throw t;
} finally {
// 如果在阻塞这段时间被打断过,那么被唤醒后返回中断标志位,被中断过,线程就进行自我打断
if (interrupted)
selfInterrupt();
}
}
/**
* 可打断获取共享锁
* @param arg
* @throws InterruptedException
*/
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
//添加到同步队列,以共享锁的方式
final AbstractQueuedSynchronizer.Node node = addWaiter(AbstractQueuedSynchronizer.Node.SHARED);
try {
for (;;) {
//获取新加入节点的前续节点
final AbstractQueuedSynchronizer.Node p = node.predecessor();
//如果前续节点是头节点则再次尝试获得锁
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
//获取锁成功,便更新头结点,并唤醒后继共享节点
setHeadAndPropagate(node, r);
p.next = null; // help GC
//当前线程结束获取锁
return;
}
}
//如果不是头结点,那么设置新节点的前驱节点的等待状态位SIGNAL,中间丢弃取消的节点
if (shouldParkAfterFailedAcquire(p, node) &&
//阻塞线程,待被唤醒后返回打断标志位,如果被打断就抛出打断异常
parkAndCheckInterrupt())
throw new InterruptedException();
}
} catch (Throwable t) {
//捕获打断异常并取消线程节点
cancelAcquire(node);
//再往上抛异常
throw t;
}
}
/**
* 带超时时间的获取共享锁
* @param arg
* @param nanosTimeout
* @return
* @throws InterruptedException
*/
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
//如果时间小于0,直接返回false,表示未获取锁
if (nanosTimeout <= 0L)
return false;
//获取加锁的截止时间
final long deadline = System.nanoTime() + nanosTimeout;
//以共享的方式加入等待队列
final AbstractQueuedSynchronizer.Node node = addWaiter(AbstractQueuedSynchronizer.Node.SHARED);
try {
for (;;) {
//获取新节点的前续节点
final AbstractQueuedSynchronizer.Node p = node.predecessor();
if (p == head) {
//如果前续节点是头结点尝试获取锁
int r = tryAcquireShared(arg);
if (r >= 0) {
//获取锁成功,将自己设置为头结点,并唤醒后续节点
setHeadAndPropagate(node, r);
p.next = null; // help GC
return true;
}
}
//如果获取锁超时则取消节点
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L) {
cancelAcquire(node);
//返回false表示获取锁失败
return false;
}
//前续节点是SIGNAL等待状态,剩余时间超过一秒,阻塞等待时间再尝试获取锁
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);//阻塞等待时间后再尝试
if (Thread.interrupted())//醒来后判断有没有被打断过,打断过就抛异常,结束获取锁
throw new InterruptedException();
}
} catch (Throwable t) {
//捕获被打断异常,取消节点
cancelAcquire(node);
//继续向上抛异常
throw t;
}
}
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();
}
/**
* 获取锁
* @param arg
*/
public final void acquire(int arg) {
//尝试加锁,具体怎么加锁由子类去实现加锁逻辑
//失败则会调用acquireQueued让线程加入队列中,如果加锁成功结束acquire方法
if (!tryAcquire(arg) &&
//加锁失败有两种情况:
//1、有线程持有锁,并且没释放,且队列没有初始化,那么让该线程初始化同步队列排队去
//1、有线程持有锁,并且没释放,但是同步队列实例化了,也就是队列至少有一个排队的线程节点,那么久排在后面
//下面这套装方法对node进行入队、再次尝试获取锁和阻塞睡眠操作(park)
acquireQueued(
//创建当前线程的node节点并加入到队列(如果同步队列未初始化,并进行初始化)
addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE), arg))
//if语句总结:尝试加锁,加锁成功结束acquire操作,加锁失败,将该线程加入同步队列中去
selfInterrupt();//加锁失败,并添加到同步队列,那么中断该线程
}
/**
* 可以被打断的获取锁,如果当前线程被打断过,抛出异常
* 如果前续节点被打断过,取消节点
* @param arg
* @throws InterruptedException
*/
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))//未获取锁成功
//带抛出异常的设置前序节点的等待状态,如果前序节点被打断了则取消该节点
doAcquireInterruptibly(arg);
}
/**
* 在等待时间内尝试获取锁
* @param arg
* @param nanosTimeout
* @return
* @throws InterruptedException
*/
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//子类实现加锁逻辑,先尝试加锁,加锁成功就返回true表示加锁成功
return tryAcquire(arg) ||
//没有加锁成功就调用带等待时间的加锁方法
doAcquireNanos(arg, nanosTimeout);
}
/**
* 释放锁并唤醒当前线程节点后的后面第一个有效等待节点
* @param arg
* @return
*/
public final boolean release(int arg) {
//解锁成功
if (tryRelease(arg)) {//tryRelease(arg)子类实现解锁逻辑
//获取头结点临时快照
AbstractQueuedSynchronizer.Node h = head;
//头结点不为空,且等待状态不为默认状态————>说明有等待节点,不是队列初始化状态
if (h != null && h.waitStatus != 0)
//唤醒头节点的第一个有效的后续节点
unparkSuccessor(h);
//唤醒后继节点后返回true,表示释放锁成功
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() {
for (AbstractQueuedSynchronizer.Node p = tail, h = head; p != h && p != null; p = p.prev)
if (p.waitStatus <= 0)
return true;
return false;
}
public final boolean hasContended() {
return head != null;
}
public final Thread getFirstQueuedThread() {
// handle only fast path, else relay
return (head == tail) ? null : fullGetFirstQueuedThread();
}
/**
* 获取等待的第一个线程节点
* @return
*/
private Thread fullGetFirstQueuedThread() {
AbstractQueuedSynchronizer.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;
//从头结点没找到,那就从尾结点找
//头结点为找到原因:在加入队列的时候节点先关联前驱节点
// 然后再更新了tail节点到新插入节点,最后才更新前驱节点到后续节点的引用,
// 所以存在那么一瞬间,从头结点往后找,node.next = null
Thread firstThread = null;
//这个循环会从尾找到头节点,一般这种情况下,排队的线程节点不多,因为head.next为null,
// 说明后面有等待节点的话都是刚刚才加上去的,还没来得及更新head.next
for (AbstractQueuedSynchronizer.Node p = tail; p != null && p != head; p = p.prev) {
Thread t = p.thread;
if (t != null)
//返回第一个等待线程
firstThread = t;
}
return firstThread;
}
public final boolean isQueued(Thread thread) {
if (thread == null)
throw new NullPointerException();
for (AbstractQueuedSynchronizer.Node p = tail; p != null; p = p.prev)
if (p.thread == thread)
return true;
return false;
}
final boolean apparentlyFirstQueuedIsExclusive() {
AbstractQueuedSynchronizer.Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}
/**
* 获取当前线程的前面是否在同步队列中存在着有排队的节点
* 即当前线程的等待节点前面有没有节点在排队
* 这个方法如果最后返回false,则去加锁,如果返回true则不加锁
* @return
*/
public final boolean hasQueuedPredecessors() {
AbstractQueuedSynchronizer.Node h, s;
//头结点不为null,说明队列已经被初始化过
if ((h = head) != null) {
//CANCELLED = 1;
//SIGNAL = -1;
//CONDITION = -2;
//PROPAGATE = -3;
//(s = h.next) == null-->头节点的next指针为空,
//或者头结点有后继节点,即有线程节点在同步队列中等待,且线程等待状态大于0,即线程节点被取消了(是个无效节点)
if ((s = h.next) == null || s.waitStatus > 0) {
s = null; // traverse in case of concurrent cancellation
//尾遍历,即从同步队列尾部开始遍历查看队列中是否有等待节点
//为什么head看了为null还要看尾遍历呢?
//添加进同步队列的时候是先让新线程添加到前一节点,让后再cas更新尾结点,最后前一节点的指针才指向新节点,
// 这里有种情况就是在那么一瞬间,从头节点遍历到不这个新节点,即前一节点的next指针还没指向新节点
//而出现head的next为null除了真没有在排队的情况,也要考虑head的next指针还没有指向第一个排队线程的情况
//for循环尾遍历,直到从尾部一直遍历到头部找到头节点后的第一个有效等待节点
// (从尾到头不管找到多少个有效节点都要循环到头部,因为要找到第一个等待节点)
for (AbstractQueuedSynchronizer.Node p = tail; p != h && p != null; p = p.prev) {
if (p.waitStatus <= 0)//小于等于0表示有效等待节点
s = p;//s记录一下
}
}
//如果头结点后有有效的等待节点,并且该线程节点的线程不是当前线程
if (s != null && s.thread != Thread.currentThread())
//返回true表示有线程节点在等待,回去不要抢锁
return true;
}
//返回false的情况,1、队列中没有有效的等待节点,2、队列中的第一个有效等待节点不是当前线程的节点(这个主要是获取重入锁)
//返回false表示没找到队列中有等待的线程,回去抢锁去吧
return false;
//下面为某个版本的写法,非常精练
//return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());
}
public final int getQueueLength() {
int n = 0;
for (AbstractQueuedSynchronizer.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<>();
for (AbstractQueuedSynchronizer.Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
}
/**
* 从同步队列中获取全部独占锁的线程
* @return
*/
public final Collection<Thread> getExclusiveQueuedThreads() {
ArrayList<Thread> list = new ArrayList<>();
for (AbstractQueuedSynchronizer.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<>();
for (AbstractQueuedSynchronizer.Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
@Override
public String toString() {
return super.toString()
+ "[State = " + getState() + ", "
+ (hasQueuedThreads() ? "non" : "") + "empty queue]";
}
/**
*检查node节点是否在同步队列
* @param node
* @return
*/
final boolean isOnSyncQueue(AbstractQueuedSynchronizer.Node node) {
//node节点的等待状态为条件等待,或者前续节点为空,说明添加进同步队列失败
if (node.waitStatus == AbstractQueuedSynchronizer.Node.CONDITION || node.prev == null)
return false;
//如果node节点的后继节点存在,说明已经添加进了同步队列
if (node.next != null) // If has successor, it must be on queue
return true;
//从尾结点开始找node节点,如果找到说明刚插入同步队列
return findNodeFromTail(node);
}
/**
* 从尾结点开始找到该node节点
* 为什么要从尾结点开始找而不是从头结点开始找呢?
* 因为在线程节点加入到同步队列的时候 先将新节点的前序索引指向尾结点,
* 然后通过CAS将新节点设置为尾结点,最后再更新原来的尾结点的后继指针指向现在的尾结点
* 所以在那么一瞬间,可能通过原来的尾结点找后继节点就是个null值
* @param node
* @return
*/
private boolean findNodeFromTail(AbstractQueuedSynchronizer.Node node) {
for (AbstractQueuedSynchronizer.Node p = tail;;) {
if (p == node)
return true;
if (p == null)
return false;
p = p.prev;
}
}
/**
* 将node(条件等待队列中的节点)加入到同步队列,
* 并设置前置节点的等待状态为SIGNAL,unpark node节点的线程
* @param node
* @return
*/
final boolean transferForSignal(AbstractQueuedSynchronizer.Node node) {
//cas将node的条件等待状态更新为0,,成功就将node加入到同步队列,没成功就返回false,
//表示从条件队列移到同步队列失败
if (!node.compareAndSetWaitStatus(AbstractQueuedSynchronizer.Node.CONDITION, 0))
return false;
//往同步队列里加node节点
AbstractQueuedSynchronizer.Node p = enq(node);
//获取添加成功节点前一节点的运行状态
int ws = p.waitStatus;
//如果大于0,表示前一线程节点已取消
//如果是有效节点,就将它的等待状态更新为SIGNAL,表示可唤醒后一节点
if (ws > 0 || !p.compareAndSetWaitStatus(ws, AbstractQueuedSynchronizer.Node.SIGNAL))
//前一节点已取消或者更改运行状态为SIGNAL失败,那么就自己唤醒刚才插入的node节点
LockSupport.unpark(node.thread);
//修改成功表示node节点添加到同步队列成功
return true;
}
/**
*将条件等待节点中的node节点添加到同步队列中
* 即,等待队列被唤醒,将其加入到同步队列抢锁
* @param node
* @return
*/
final boolean transferAfterCancelledWait(AbstractQueuedSynchronizer.Node node) {
//将node的等待状态从条件等待改成0
if (node.compareAndSetWaitStatus(AbstractQueuedSynchronizer.Node.CONDITION, 0)) {
//往同步队列中添加node线程节点 全路径 + 优化前置方式
enq(node);
//加入成功。返回true
return true;
}
//检查node节点是否在同步队列,如果不在同步队列,释放CPU的使用权
while (!isOnSyncQueue(node))
Thread.yield();
return false;
}
/**
* 调用release操作唤醒竞争队列的节点。
* 注意:当前线程的state变量,也即控制可重入的变量需要保存,因为在后面唤醒后要恢复状态
* @param node
* @return
*/
final int fullyRelease(AbstractQueuedSynchronizer.Node node) {
try {
int savedState = getState();
//释放锁操作
if (release(savedState))
//释放成功,返回 state的值
return savedState;
//释放失败,抛出非法锁状态异常
throw new IllegalMonitorStateException();
} catch (Throwable t) {
//捕获,设置当前节点为取消状态
node.waitStatus = AbstractQueuedSynchronizer.Node.CANCELLED;
throw t;
}
}
public final boolean owns(AbstractQueuedSynchronizer.ConditionObject condition) {
return condition.isOwnedBy(this);
}
public final boolean hasWaiters(AbstractQueuedSynchronizer.ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.hasWaiters();
}
public final int getWaitQueueLength(AbstractQueuedSynchronizer.ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitQueueLength();
}
public final Collection<Thread> getWaitingThreads(AbstractQueuedSynchronizer.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;
/** First node of condition queue. */
private transient AbstractQueuedSynchronizer.Node firstWaiter;//同步队列用head
/** Last node of condition queue. */
private transient AbstractQueuedSynchronizer.Node lastWaiter;//同步队列用的是tail
/**
* Creates a new {@code ConditionObject} instance.
*/
public ConditionObject() { }
// Internal methods
/**
*往条件等待队列中新添加一个新的等待节点
*
*/
private AbstractQueuedSynchronizer.Node addConditionWaiter() {
//当前线程是不是获取独占锁的线程(ReentrantLock类判断)
if (!isHeldExclusively())//不是便抛出异常
throw new IllegalMonitorStateException();
//获取最后一个等待节点临时快照
AbstractQueuedSynchronizer.Node t = lastWaiter;
// 如果最后一个等待节点不为空,并且不是条件等待状态则移除等待队列中的取消节点或者非条件等待节点
if (t != null && t.waitStatus != AbstractQueuedSynchronizer.Node.CONDITION) {
unlinkCancelledWaiters();
//更新临时快照为最后一个等待节点
t = lastWaiter;
}
//创建条件等待节点
AbstractQueuedSynchronizer.Node node = new AbstractQueuedSynchronizer.Node(AbstractQueuedSynchronizer.Node.CONDITION);
//如果最后一个条件等待节点快照为null,因为上面经过了非条件节点和取消节点的清理,所以还未空,那么条件等待队列为kong
if (t == null)
//所以第一个条件等待就为node
firstWaiter = node;
else
//条件等待队列不为空,则在队列后将node加入进去
t.nextWaiter = node;
//更新lastWaiter
lastWaiter = node;
//添加成功返回node节点
return node;
}
private void doSignal(AbstractQueuedSynchronizer.Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
/**
* 从等待队列中的第一节点开始,唤醒所有(共享)等待线程
* @param first
*/
private void doSignalAll(AbstractQueuedSynchronizer.Node first) {
//先将第一等待者和最后等待者都置空,因为要唤醒所有的等待队列线程了
lastWaiter = firstWaiter = null;
do {
//记录条件等待队列的下一等待节点快照
AbstractQueuedSynchronizer.Node next = first.nextWaiter;
//first节点的nextwaiter置空
first.nextWaiter = null;
//将first节点加入到同步队列中
transferForSignal(first);
//first更新为它的后一个等待者
first = next;
} while (first != null);//while循环逐一将条件等待队列的节点加入到同步队列
}
/**
* 从第一个等待节点开始移除队列中取消的或者非条件等待节点
*/
private void unlinkCancelledWaiters() {
//获取第一个等待节点记录到临时t节点中(快照第一等待节点)
AbstractQueuedSynchronizer.Node t = firstWaiter;
//trail临时记录条件等待线程节点
AbstractQueuedSynchronizer.Node trail = null;
while (t != null) {
//获取等待队列下一节点
AbstractQueuedSynchronizer.Node next = t.nextWaiter;
//判断当前节点是不是条件等待节点
if (t.waitStatus != AbstractQueuedSynchronizer.Node.CONDITION) {
//不是条件等待状态,把当前节点的nextWaiter指针置空,先断后边的指针
t.nextWaiter = null;
//如果trail为null,也就是说还没遍历出是条件等待节点,
//那么原来的firstWaiter为非等待节点,那么就更新为它的下一个等待节点
if (trail == null)
firstWaiter = next;
else
//前面记录了有有效的条件等待节点,那么就更新nextWaiter为next这个节点
trail.nextWaiter = next;
if (next == null)//如果next节点为空,说明等待队列遍历完了,把记录的有效等待节点设为最后一个等待节点
lastWaiter = trail;
}
else//如果t节点是条件等待状态,把该节点赋给trail节点(记录下这个条件等待节点)
trail = t;
t = next;//更新临时t节点
}
}
/**
* 唤醒等待队列的第一个等待线程(共享)
*/
@Override
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
AbstractQueuedSynchronizer.Node first = firstWaiter;
if (first != null)
doSignal(first);
}
/**
* 唤醒所有(共享锁线程(读锁))
*/
@Override
public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
AbstractQueuedSynchronizer.Node first = firstWaiter;
if (first != null)
//等待队列中还有等待节点,从第一个等待节点开始逐个唤醒队列中的等待节点(共享)
doSignalAll(first);
}
public final void awaitUninterruptibly() {
AbstractQueuedSynchronizer.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;
/** Mode meaning to throw InterruptedException on exit from wait */
private static final int THROW_IE = -1;
/**
*检查在等待过程中是否被打断过
* 打断过,再判断是否将该节点放入了同步队列,
* 如果放入了就返回THROW_IE的状态值
* 如果没有插入同步队列,返回再次打断的状态值
* 没打断过返回0;
* @param node
* @return
*/
private int checkInterruptWhileWaiting(AbstractQueuedSynchronizer.Node node) {
//THROW_IE:表示在从等待中被唤醒时抛出异常的一个状态值
//transferAfterCancelledWait(node)-->node节点是否插入同步队列成功
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}
/**
* 处理打断状态 THROW_IE-->抛异常
* REINTERRUPT-->打断当前线程
* @param interruptMode
* @throws InterruptedException
*/
private void reportInterruptAfterWait(int interruptMode)
throws InterruptedException {
if (interruptMode == THROW_IE)
throw new InterruptedException();
else if (interruptMode == REINTERRUPT)
selfInterrupt();
}
/**
* 阻塞等待队列的线程,并唤醒竞争队列的线程
* @throws InterruptedException
*/
public final void await() throws InterruptedException {
//如果线程被打断过,恢复标志位并抛出异常
if (Thread.interrupted())
throw new InterruptedException();
//往条件等待队列中新添加一个等待线程
AbstractQueuedSynchronizer.Node node = addConditionWaiter();
//调用fullyRelease操作唤醒 竞争队列 的节点。
int savedState = fullyRelease(node);
int interruptMode = 0; //状态有 0:默认 1 再次打断 2 节点在同步队列中且等待过程中被打断,再次唤醒要求抛异常
//node节点不在同步队列中才进入循环
//while操作总结:将条件等待队列中的线程全部阻塞
while (!isOnSyncQueue(node)) {
//阻塞该线程
LockSupport.park(this);
//检查在等待过程中是否被打断过,如果是1 表示再次打算,-1表示打断过且添加进了同步队列
//if总结:如果是被打断过,就结束循环
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//被唤醒后往下执行,此时条件队列中的线程节点都在同步队列中
//将node节点加入同步队列成功,并且打断状态为在THROW_IE THROW_IE-->在等待过程中被打断过,唤醒时要求抛异常的状态
//if总结:node节点已经加入到了同步队列,且等待过程中被打断过,那么打断标志设为再次打断状态
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;//方法内的打断标志为 再次打算状态
//node节点在条件等待队列,且它有后续节点
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();//从第一个等待节点开始移除队列中取消的或者非条件等待节点
if (interruptMode != 0)
//处理打断标志的结果,即THROW_IE去抛异常,REINTERRUPT去做自我打断
reportInterruptAfterWait(interruptMode);
}
/**
* 再要求的时间内阻塞等待队列的线程,并唤醒竞争队列的线程
* @param nanosTimeout
* @return
* @throws InterruptedException
*/
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// We don't check for nanosTimeout <= 0L here, to allow
// awaitNanos(0) as a way to "yield the lock".
//截止时间
final long deadline = System.nanoTime() + nanosTimeout;
long initialNanos = nanosTimeout;
//将节点加入到条件的等待队列
AbstractQueuedSynchronizer.Node node = addConditionWaiter();
//调用release操作唤醒竞争队列的节点。
int savedState = fullyRelease(node);
int interruptMode = 0;//状态有 0:默认 1 再次打断 -1 节点在同步队列中且等待过程中被打断,再次唤醒要求抛异常
//node节点不在同步队列中才进入循环
//while操作总结:将在规定时间内,使条件等待队列中的线程全部阻塞,时间过后便不再处理让其阻塞
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
//如果剩余时间大于1秒,便让其阻塞剩余时间
if (nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
//如果打断标志为 1 或者-1结束循环 --->1 再次打断 -1 节点在同步队列中且等待过程中被打断,再次唤醒要求抛异常
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
//将node节点加入同步队列成功,并且打断状态为在THROW_IE THROW_IE-->在等待过程中被打断过,唤醒时要求抛异常的状态
//if总结:node节点已经加入到了同步队列,且等待过程中被打断过,那么打断标志设为再次打断状态
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;//方法内的打断标志为 再次打算状态
//node节点在条件等待队列,且它有后续节点
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();//从第一个等待节点开始移除队列中取消的或者非条件等待节点
if (interruptMode != 0)
//处理打断标志的结果,即THROW_IE去抛异常,REINTERRUPT去做自我打断
reportInterruptAfterWait(interruptMode);
long remaining = deadline - System.nanoTime(); // avoid overflow
return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE;
}
/**
* 阻塞到给定的时间截点
* @param deadline
* @return
* @throws InterruptedException
*/
@Override
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
//将节点加入到条件的等待队列
AbstractQueuedSynchronizer.Node node = addConditionWaiter();
//调用release操作唤醒竞争队列的节点。
int savedState = fullyRelease(node);
boolean timedout = false;
int interruptMode = 0;//状态有 0:默认 1 再次打断 -1 节点在同步队列中且等待过程中被打断,再次唤醒要求抛异常
//node节点不在同步队列中才进入循环
//while操作总结:将在规定时间内,使条件等待队列中的线程全部阻塞,时间过后便不再处理让其阻塞
while (!isOnSyncQueue(node)) {
//当前时间超过截止时间便将条件等待节点中的node节点添加到同步队列中
if (System.currentTimeMillis() >= abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
//将当前线程阻塞到abstime
LockSupport.parkUntil(this, abstime);
//检查在等待过程中是否被打断过,如果是1 表示再次打算,-1表示打断过且添加进了同步队列
//if总结:如果是被打断过,就结束循环
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//将node节点加入同步队列成功,并且打断状态为在THROW_IE THROW_IE-->在等待过程中被打断过,唤醒时要求抛异常的状态
//if总结:node节点已经加入到了同步队列,且等待过程中被打断过,那么打断标志设为再次打断状态
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;//方法内的打断标志为 再次打算状态
//node节点在条件等待队列,且它有后续节点
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();//从第一个等待节点开始移除队列中取消的或者非条件等待节点
if (interruptMode != 0)
//处理打断标志的结果,即THROW_IE去抛异常,REINTERRUPT去做自我打断
reportInterruptAfterWait(interruptMode);
return !timedout;
}
/**
* 带时间单位的阻塞
* @param time
* @param unit
* @return
* @throws InterruptedException
*/
@Override
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
// We don't check for nanosTimeout <= 0L here, to allow
// await(0, unit) as a way to "yield the lock".
final long deadline = System.nanoTime() + nanosTimeout;
//将节点加入到条件的等待队列
AbstractQueuedSynchronizer.Node node = addConditionWaiter();
//调用release操作唤醒同步队列的节点。
int savedState = fullyRelease(node);
boolean timedout = false;
int interruptMode = 0;//状态有 0:默认 1 再次打断 -1 节点在同步队列中且等待过程中被打断,再次唤醒要求抛异常
//在nanosTimeout时间后将node节点添加到同步队列,加入成功退出循环
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
//当前时间超过截止时间便将条件等待节点中的node节点添加到同步队列中
timedout = transferAfterCancelledWait(node);
break;
}
//将当前线程阻塞到nanosTimeout
if (nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
//检查在等待过程中是否被打断过,如果是1 表示再次打算,-1表示打断过且添加进了同步队列
//if总结:如果是被打断过,就结束循环
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
//将node节点加入同步队列成功,并且打断状态为在THROW_IE THROW_IE-->在等待过程中被打断过,唤醒时要求抛异常的状态
//if总结:node节点已经加入到了同步队列,且等待过程中被打断过,那么打断标志设为再次打断状态
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;//方法内的打断标志为 再次打算状态
//node节点在条件等待队列,且它有后续节点
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();//从第一个等待节点开始移除队列中取消的或者非条件等待节点
if (interruptMode != 0)
//处理打断标志的结果,即THROW_IE去抛异常,REINTERRUPT去做自我打断
reportInterruptAfterWait(interruptMode);
return !timedout;
}
final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
return sync == AbstractQueuedSynchronizer.this;
}
/**
* 等待队列是否有等待节点
* @return
*/
protected final boolean hasWaiters() {
//如果持有的是共享锁(读锁)抛出异常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//等待队列是否有等待节点
for (AbstractQueuedSynchronizer.Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == AbstractQueuedSynchronizer.Node.CONDITION)
return true;
}
return false;
}
protected final int getWaitQueueLength() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int n = 0;
for (AbstractQueuedSynchronizer.Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == AbstractQueuedSynchronizer.Node.CONDITION)
++n;
}
return n;
}
/**
* 获取所有的等待线程
* @return
*/
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList<Thread> list = new ArrayList<>();
for (AbstractQueuedSynchronizer.Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == AbstractQueuedSynchronizer.Node.CONDITION) {
Thread t = w.thread;
if (t != null)
list.add(t);
}
}
return list;
}
}
// VarHandle mechanics
//这三个变量对应state head tail指向同一块内存,即两者都是一样的
//但是使用这个引用操作对象是原子性的,线程安全的,
// 操作结果最终也落到了state head tail变量的头上
//原子操作例子如下面的initializeSyncQueue()方法
private static final VarHandle STATE;
private static final VarHandle HEAD;
private static final VarHandle TAIL;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
STATE = l.findVarHandle(AbstractQueuedSynchronizer.class, "state", int.class);
HEAD = l.findVarHandle(AbstractQueuedSynchronizer.class, "head", AbstractQueuedSynchronizer.Node.class);
TAIL = l.findVarHandle(AbstractQueuedSynchronizer.class, "tail", AbstractQueuedSynchronizer.Node.class);
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
Class<?> ensureLoaded = LockSupport.class;
}
/**
* 初始化同步队列,即创建一个节点,但是线程为null,头尾结点也指向它
*/
private final void initializeSyncQueue() {
AbstractQueuedSynchronizer.Node h;
if (HEAD.compareAndSet(this, null, (h = new AbstractQueuedSynchronizer.Node())))
tail = h;
}
/**
* 原子操作更新尾结点
*/
private final boolean compareAndSetTail(AbstractQueuedSynchronizer.Node expect, AbstractQueuedSynchronizer.Node
update) {
return TAIL.compareAndSet(this, expect, update);
}
}