AbstractQueuedSynchronizer源码分析

1、简介

        AQS是JUC框架中重要的类,经过它来实现独占锁和共享锁的,内部不少类都是经过AQS来实现的,好比CountDownLatch、ReentrantLock、ReentrantReadWriteLock、Semaphore。本章是对AbstractQueuedSynchronizer源码进行分析。从独占锁的获取、释放,共享锁的获取、释放,以及Condition的await、signal三方面对源码进行分析。先知道AQS的这几点注意事项一、Condition条件变量只支持在独占锁状态下二、AQS支持同步队列和条件队列(条件队列的数目根据Condition实例的数目),只有同步队列中的节点线程才能获取锁三、AQS是个抽象类,提供独占锁和共享锁的公有方法,子类须要实现的几个模板方法,①tryAcquire②tryRelease③tryAcquireShared④tryReleaseShared⑤isHeldExclusively。这几点在下面代码解析会分析到。还有一个AbstractQueuedLongSynchronizer类,它与AQS功能和实现几乎同样,惟一不一样的是AQLS中表明锁被获取次数的属性state类型是long类型,而AQS中该成员变量是int类型。AQS源码对应的jdk版本是1.8。java

2、类关系


//此类只提供保存和获取独占锁线程,子类可使用适当的保留值来帮助控制和监控访问并提供诊断
public abstract class AbstractOwnableSynchronizer implements java.io.Serializable {
    
    private static final long serialVersionUID = 3737899427754241961L;
    
    protected AbstractOwnableSynchronizer() { }
    
    //独占锁拥有者线程
    private transient Thread exclusiveOwnerThread;
     
    //设置独占锁的拥有者线程,访问权限protected,同包或者子类使用
    protected final void setExclusiveOwnerThread(Thread thread) {
        //将传入进来的线程赋值给独占锁拥有者线程
        exclusiveOwnerThread = thread;
    }
    
    //获取独自锁的拥有者线程,访问权限protected,只能在同包或者子类使用
    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }
}复制代码

3、属性

//同步队列的头节点
private transient volatile Node head;
//同步队列的尾节点
private transient volatile Node tail;
//同步状态
private volatile int state;
//若是超时时间小于此阈值,不阻塞线程,让其自旋,在doAcquireNanos、doAcquireSharedNanos、awaitNanos、await(long time, TimeUnit unit)方法使用到
static final long spinForTimeoutThreshold = 1000L;
//获取UnSafe使用,若是对UnSafe使用不清楚的,能够看下我分享的UnSafe的使用
private static final Unsafe unsafe = Unsafe.getUnsafe();
//属性state的相对偏移量,相对AbstractQueuedSynchronizer实例的起始内存位置的相对偏移量,定义成静态的缘由是,属性的相对实例的偏移量都是相等的
private static final long stateOffset;
//属性head的相对偏移量
private static final long headOffset;
//属性tail的相对偏移量
private static final long tailOffset;
//内部类Node实例的属性waitStatus的相对偏移量
private static final long waitStatusOffset;
//内部类Node实例的属性next的相对偏移量
private static final long nextOffset;
static {
    try {
        //使用UnSafe实例获取AbstractQueuedSynchronizer类的属性state的相对偏移量
        stateOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
        //使用UnSafe实例获取AbstractQueuedSynchronizer类的属性head的相对偏移量
        headOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
        //使用UnSafe实例获取AbstractQueuedSynchronizer类的属性tail的相对偏移量
        tailOffset = unsafe.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
        //使用UnSafe实例获取AbstractQueuedSynchronizer内部类Node的属性waitStatus的相对偏移量
        waitStatusOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("waitStatus"));
        //使用UnSafe实例获取AbstractQueuedSynchronizer内部类Node的属性next的相对偏移量
        nextOffset = unsafe.objectFieldOffset
                (Node.class.getDeclaredField("next"));
    } catch (Exception ex) { throw new Error(ex); }    
}复制代码

4、内部类

  1. Node类

    //经过Node咱们能够实现两个队列,一是经过prev和next属性实现CLH队列(线程同步队列,双向队列),二是nextWaiter属性实现Condition条件上的等待条件队列(单向队列),在Condition中会详细介绍。
    static final class Node {
            //当前节点是获取共享锁的标记
            static final Node SHARED = new Node();
            //当前节点是获取独占锁的标记
            static final Node EXCLUSIVE = null;
            
            //属性waitStatus的值,标志节点对应的线程被取消
            static final int CANCELLED =  1;
            //属性waitStatus的值,标志当前节点的next节点的线程(即队列中当前节点的下一个节点)须要被阻塞
            static final int SIGNAL    = -1;
            //属性waitStatus的值,标志当前节点在Condition条件下等待阻塞,在Condition实例的await系列方法中使用,新建一个waitStatus的值为CONDITION的节点Node,将其加入到Condition中的条件队列中,在Condition实现类详细介绍
            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;
            
            //有两种做用:一、表示下一个在Condition条件上等待的节点,调用Condition中await和signal方法,当前节点的线程是拥有独占锁的线程二、表示同步队列中的节点是共享模式仍是独占模式
            Node nextWaiter;
            
            //判断当前节点是否是共享模式
            final boolean isShared() {
                return nextWaiter == SHARED;
            }
            
            //获取当前节点的前驱节点,若是为null,则抛出空指针异常
            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;
                //将传入进来的线程赋值给节点属性thread
                this.thread = thread;
            }
            
            //在Condition条件中使用
            Node(Thread thread, int waitStatus) {
                //将传入节点的状态值赋值给节点属性waitStatus 
                this.waitStatus = waitStatus;
                //将传入进来的线程赋值给节点属性thread
                this.thread = thread;
            }
    }
    
    复制代码

  2. ConditionObject类

    public interface Condition {
        //如下方法都会详细在ConditionObject实现类中介绍 
        void await() throws InterruptedException;
        
        void awaitUninterruptibly();
        
        long awaitNanos(long nanosTimeout) throws InterruptedException;
        
        boolean await(long time, TimeUnit unit) throws InterruptedException;
    
        boolean awaitUntil(Date deadline) throws InterruptedException;
        
        void signal();
    
        void signalAll();
    }
    
    
    
    public class ConditionObject implements Condition, java.io.Serializable {
            private static final long serialVersionUID = 1173984872572414699L;
            //当前Condition实例的条件队列的第一个节点
            private transient Node firstWaiter;
            //当前Condition实例的条件队列的最后一个节点 
            private transient Node lastWaiter;
            //构造函数
            public ConditionObject() { }
            
            //若是尾节点的状态值不是CONDITION值,清除条件队列中取消的节点,修改条件队列的第一个节点和最后一个节点,建立新节点,将其新节点作为条件队列的尾节点
            private Node addConditionWaiter() {
                //获取条件队列的最后一个节点
                Node t = lastWaiter;
                // If lastWaiter is cancelled, clean out.
                //若是条件队列中的最后一个节点不为空,而且状态值不是CONDITION,即最后等待节点已取消
                if (t != null && t.waitStatus != Node.CONDITION) {
                    //移除条件队列中的已取消的节点,从新设置firstWaiter、lastWaiter节点,详细的能够看下面对unlinkCancelledWaiters方法的介绍
                    unlinkCancelledWaiters();
                    //从新获取条件队列的最后一个节点
                    t = lastWaiter;
                }
                //建立新节点,传入当前线程和节点的状态值Node.CONDITION
                Node node = new Node(Thread.currentThread(), Node.CONDITION);
                //若是尾节点为空
                if (t == null)
                    //将其新节点作为条件队列的第一个节点
                    firstWaiter = node;
                else
                    //将条件队列中的上一个尾节点
                    t.nextWaiter = node;
                //将其新建的节点作为条件队列的最后一个节点
                lastWaiter = node;
                //返回新建的节点
                return node;
            }
            
            //只将一个条件队列中不为空、状态值为CONDITION的第一个节点加入到同步队列中,传入条件队列的头结点,将其移动同步队列中,若是传入的节点已取消,会将其传入节点的下一个不为空、状态值为CONDITION的节点移到同步队列中
            private void doSignal(Node first) {
                do {
                    //传入的节点的下一个等待节点为空
                    if ( (firstWaiter = first.nextWaiter) == null)
                        //将其条件队列的尾节点设置为空 
                        lastWaiter = null;
                    //加快gc回收,将其传入节点的下一节点置为空 
                    first.nextWaiter = null;
                    //能够看下面对transferForSignal方法的详细介绍,将其传入节点(状态值为CONDITION)移到同步队列中,若是当前加入同步队列节点的前置节点状态为已取消,或者将其前置节点的状态值设置为SIGNAL失败,唤醒加入的节点对应的线程
                } while (!transferForSignal(first) && //找到条件队列中节点不为空的而且状态值为CONDITION的节点加入到同步队列中
                         (first = firstWaiter) != null);
            }
            
            //将其条件队列中的全部不为空、状态值为CONDITION的节点加入到同步队列中,从传入条件队列的头节点开始
            private void doSignalAll(Node first) {
                //将其条件队列的头尾节点都置为空
                lastWaiter = firstWaiter = null;
                //从头结点开始循环获取条件队列中的全部节点
                do {
                    //获取头结点的下一节点
                    Node next = first.nextWaiter;
                    //加快gc,将其头节点的关联的下一节点置为空
                    first.nextWaiter = null;
                    //能够看下面对transferForSignal方法的详细介绍,将其传入节点(状态值为CONDITION)移到同步队列中,若是当前加入同步队列节点的前置节点状态为已取消,或者将其前置节点的状态值设置为SIGNAL失败,唤醒加入的节点对应的线程
                    transferForSignal(first);
                    //将下一节点设置为头结点
                    first = next;
                } while (first != null);//直到节点为空,即条件队列结束
            }
            
            //将已取消的节点从条件队列中移除 
            private void unlinkCancelledWaiters() {
                //获取条件队列的头节点
                Node t = firstWaiter;
                //临时变量,存放最新的不为空、状态值为Node.CONDITION的节点,目的是为了设置下一节点不为空、状态值为Node.CONDITION的节点
                Node trail = null;
                //头结点不为空
                while (t != null) {
                    //获取头节点的下一节点
                    Node next = t.nextWaiter;
                    //若是头节点状态值不是Node.CONDITION,此节点已取消 
                    if (t.waitStatus != Node.CONDITION) {
                        //加快gc,此已取消节点
                        t.nextWaiter = null; 
                        //若是最新的不为空、状态值为CONDITION的节点为空
                        if (trail == null)
                            //将下一节点设置为头结点
                            firstWaiter = next;
                        else
                            //将最新的不为空、状态值为CONTIDION的节点和下一节点连起来
                            trail.nextWaiter = next;
                        //若是下一节点为空,代表条件队列已经没有节点
                        if (next == null)
                            //将最新的不为空、状态值为CONTIDION的节点赋值给尾节点 
                            lastWaiter = trail;
                    }
                    else
                        //将t赋值给trail
                        trail = t;
                    将下一节点作为头节点
                    t = next;
                }
            }
            
            // public methods
            //将条件队列中的不为空、状态值为CONDITION头节点移动到同步队列中 
            public final void signal() {
                //调用signal方法的线程,不是拥有排他锁的线程就会抛出IllegalMonitorStateException异常,Condition的使用只支持在排他锁下使用
                if (!isHeldExclusively()) //isHeldExclusively方法子类得重写,不然直接抛出UnsupportedOperationException
                    throw new IllegalMonitorStateException();
                //获取条件队列的头结点
                Node first = firstWaiter;
                //若是条件队列不为空
                if (first != null)
                    //调用上面介绍的doSignal方法,详细的能够看上面的介绍,只将一个条件队列中不为空、状态值为CONDITION的第一个节点加入到同步队列中,传入条件队列的头结点,将其移动同步队列中,若是传入的节点已取消,会将其传入节点的下一个不为空、状态值为CONDITION的节点移到同步队列中
                    doSignal(first);
            }
            
            //将条件队列中的全部不为空,状态值为CONDITION的节点移动到同步队列中
            public final void signalAll() {
                /调用signalAll方法的线程,不是拥有排他锁的线程就会IllegalMonitorStateException异常,Condition的使用只支持在排他锁下使用
                if (!isHeldExclusively())
                    throw new IllegalMonitorStateException();
                //获取条件队列中的头节点
                Node first = firstWaiter;
                //若是头节点不为空,即条件队列中存在节点
                if (first != null)
                    //调用上面介绍的doSignalAll方法,doSignalAll方法的详细介绍能够看上面对此方法的介绍,将其条件队列中的全部不为空、状态值为CONDITION的节点加入到同步队列中,从传入条件队列的头节点开始
                    doSignalAll(first);
            }
            
            //新建个节点加入到同步队列中,并释放锁,让当前线程阻塞等待。若是线程等待期间发出中断请求,不会产生中断异常
            public final void awaitUninterruptibly() {
                //为当前线程建立新的Node节点,而且将此节点加入到条件队列中,addConditionWaiter方法能够看上面对此方法的介绍
                Node node = addConditionWaiter();
                //释放当前线程占有的锁,并唤醒其余线程,fullRelease方法会在下面详细介绍到
                int savedState = fullyRelease(node);
                //初始化中断标志位为false
                boolean interrupted = false;
                //循环判断当前新建的节点是否在同步队列中,直到此节点在同步队列中退出循环,不然就阻塞当前线程,isOnSyncQueue方法会在下面进行介绍
                while (!isOnSyncQueue(node)) {
                    //阻塞当前线程
                    LockSupport.park(this);
                    //若是当前线程被中断 
                    if (Thread.interrupted())
                        //将中断标志位设置为true
                        interrupted = true;
                }
                //节点已经在同步队列中,获取同步锁,只有获得锁才能继续执行,不然线程继续阻塞等待,acquireQueued方法返回当前线程是否被中断,此方法会在下面详细进行介绍
                if (acquireQueued(node, savedState) || interrupted)
                    //acquireQueued方法返回true,即当前线程被中断过,或者interruped标志位为true调用当前线程的interrupt方法
                    selfInterrupt();//Thread.currentThread().interrupt();
            }
    
            //从新中断的标志位
            private static final int REINTERRUPT =  1;
            //抛出中断异常的标志位 
            private static final int THROW_IE    = -1;
            
            //检查传入节点在等待时,传入节点对应的线程是否有发生被中断请求
            //若是其余线程没有调用传入节点线程的interrupt方法,即中断请求,返回0
            //若是此节点对应的线程有被中断请求,而且中断请求在signalled(即调用signal或signalAll)以前返回THROW_IE ,由于在调用await方法时,会新建一个节点(状态值为CONDITION)加入到条件队列中,好比调用await方法传入超时时间,阻塞线程在超时自动被唤醒,此时节点尚未被signal,可是有其余线程调用此节点对应的线程interrupt方法
            //若是中断请求是在singal、signalAll方法以后,返回从新中断的标志位
            private int checkInterruptWhileWaiting(Node node) {
                return Thread.interrupted() ?
                    //transferAfterCanceledWait方法,看下面的详细介绍 
                    (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                    0;
            }
    
            //若是传入进来的参数interruptMode是THROW_IE,就抛出InterruptedException异常,若是interruptMode是REINTERRUPT,则当前线程再次调用interrupt方法,再次发出中断请求,不然就什么都不作
            private void reportInterruptAfterWait(int interruptMode) throws InterruptedException {
                //若是interruptMode是THROW_IE 
                if (interruptMode == THROW_IE)
                    //抛出InterruptedException异常
                    throw new InterruptedException();
                //若是interruptMode是REINTERRUPT,从新调用当前线程的interrupt方法,再次发出中断请求
                else if (interruptMode == REINTERRUPT)
                    selfInterrupt();
            }
    
            //新建个节点加入到同步队列中,并释放锁,让当前线程阻塞等待。若是线程等待期间发出中断请求,则抛出中断异常
            public final void await() throws InterruptedException {
                //若是当前线程已被中断
                if (Thread.interrupted())
                    //抛出中断异常
                    throw new InterruptedException();
                //为当前线程建立新的Node节点,而且将此节点加入到条件队列中,addConditionWaiter方法能够看上面对此方法的介绍
                Node node = addConditionWaiter();
                //释放当前线程占有的锁,并唤醒其余线程,fullRelease方法会在下面详细介绍到
                int savedState = fullyRelease(node);
                //线程中断请求是在signal、signalAll方法将此节点加入到同步队列以前仍是以后的标志位 
                int interruptMode = 0;
                //循环判断当前新建的节点是否在同步队列中,直到此节点在同步队列中退出循环,不然就阻塞当前线程,isOnSyncQueue方法会在下面进行介绍
                while (!isOnSyncQueue(node)) {
                    //阻塞当前线程
                    LockSupport.park(this);
                    //若是当前线程产生中断请求,就跳出循环, checkInterruptWhileWaiting方法能够看上面对此方法的介绍
                    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                        break;
                }
                //节点已经在同步队列中,获取同步锁,只有获得锁才能继续执行,不然线程继续阻塞等待,acquireQueued方法返回当前线程是否被中断,此方法会在下面详细进行介绍
                if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                    interruptMode = REINTERRUPT;
                //若是当前节点的下一个节点不为空 
                if (node.nextWaiter != null) // clean up if cancelled
                    //将已取消的节点从条件队列中移除能够看上面对unlinkCancelledWaiters方法介绍
                    unlinkCancelledWaiters();
                //是否要抛出中断异常,或者发出中断请求
                if (interruptMode != 0)
                    //能够看上面对reportInterruptAfterWait方法的介绍
                    reportInterruptAfterWait(interruptMode);
            }
            
            //@param nanpsTimeout超时时间,单位为纳秒
            //@return 死亡时间减去当前时间的时间戳
            //新建个节点加入到同步队列中,并释放锁,让当前线程阻塞等待,直到被调用signal、signalAll方法,或者超时将当前节点从条件队列中移到同步队列中,在同步队列中阻塞获得获取锁。若是线程等待期间发出中断请求,则抛出中断异常
            public final long awaitNanos(long nanosTimeout) throws InterruptedException {
                //若是线程已被中断 
                if (Thread.interrupted())
                    //抛出中断异常
                    throw new InterruptedException();
                //为当前线程建立新的Node节点,而且将此节点加入到条件队列中,addConditionWaiter方法能够看上面对此方法的介绍
                Node node = addConditionWaiter();
                //释放当前线程占有的锁,并唤醒其余线程,fullRelease方法会在下面详细介绍到
                int savedState = fullyRelease(node);
                //获取死亡时间,即当前时间加上传入的超时时间 
                final long deadline = System.nanoTime() + nanosTimeout;
                //线程中断请求是在signal、signalAll方法将此节点加入到同步队列以前仍是以后的标志位 
                int interruptMode = 0;
                //循环判断当前新建的节点是否在同步队列中,直到此节点在同步队列中退出循环,不然就阻塞当前线程,isOnSyncQueue方法会在下面进行介绍
                while (!isOnSyncQueue(node)) {
                    //若是传入的超时时间小于等于0
                    if (nanosTimeout <= 0L) {
                        //transferAfterCanceledWait方法,看下面的详细介绍 
                        transferAfterCancelledWait(node);
                        //退出循环
                        break;
                    }
                    //若是超时时间大于等于spinForTimeoutThreshold阈值,才会阻塞当前线程,不然让其线程自旋一段时间
                    if (nanosTimeout >= spinForTimeoutThreshold)
                        //超时的阻塞当前线程,this是阻塞当前线程的监控对象
                        LockSupport.parkNanos(this, nanosTimeout);
                    //若是当前线程产生中断请求,就跳出循环, checkInterruptWhileWaiting方法能够看上面对此方法的介绍
                    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                        //退出循环 
                        break;
                    //死亡时间减去当前时间,获得超时时间
                    nanosTimeout = deadline - System.nanoTime();
                }
                //节点已经在同步队列中,获取同步锁,只有获得锁才能继续执行,不然线程继续阻塞等待,acquireQueued方法返回当前线程是否被中断,此方法会在下面详细进行介绍
                if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                    //将其标志节点interruptMode设置为从新中断标志位
                    interruptMode = REINTERRUPT;
                //若是当前节点的下一个节点不为空 
                if (node.nextWaiter != null)
                    //将已取消的节点从条件队列中移除,能够看上面对unlinkCancelledWaiters方法介绍
                    unlinkCancelledWaiters();
                //是否要抛出中断异常,或者发出中断请求
                if (interruptMode != 0)
                    //能够看上面对reportInterruptAfterWait方法的介绍
                    reportInterruptAfterWait(interruptMode);
                //返回死亡时间减去当前时间的时间戳
                return deadline - System.nanoTime();
            }
            
            //@param deadline 死亡时间
            //@return 节点对应的线程被中断是否比占有独占锁的线程调用signal、signalAll方法将当前节点从条件队列移到同步队列中以前,若是是返回值为false,不然返回true,表示正常超时,而不是由中断退出
            //新建个节点加入到同步队列中,并释放锁,让当前线程阻塞等待,直到被调用signal、signalAll方法,或者到死亡时间将当前节点从条件队列中移到同步队列中,在同步队列中阻塞获得获取锁。若是线程等待期间发出中断请求,则抛出中断异常
            public final boolean awaitUntil(Date deadline) throws InterruptedException {
                //死亡时间的时间戳 
                long abstime = deadline.getTime();
                //若是线程已被中断 
                if (Thread.interrupted())
                    //抛出中断异常
                    throw new InterruptedException();
                //为当前线程建立新的Node节点,而且将此节点加入到条件队列中,addConditionWaiter方法能够看上面对此方法的介绍
                Node node = addConditionWaiter();
                //释放当前线程占有的锁,并唤醒其余线程,fullRelease方法会在下面详细介绍到
                int savedState = fullyRelease(node);
                //是否超时的标记位
                boolean timedout = false;
                //线程中断请求是在signal、signalAll方法将此节点加入到同步队列以前仍是以后的标志位
                int interruptMode = 0;
                //循环判断当前新建的节点是否在同步队列中,直到此节点在同步队列中退出循环,不然就阻塞当前线程,isOnSyncQueue方法会在下面进行介绍
                while (!isOnSyncQueue(node)) {
                    //若是当前时间大于死亡时间 
                    if (System.currentTimeMillis() > abstime) {
                        //transferAfterCanceledWait方法,看下面的详细介绍 
                        timedout = transferAfterCancelledWait(node);
                        //退出循环
                        break;
                    }
                    //阻塞当前线程直到死亡时间、或者拥有独占锁的线程调用signal、signalAll方法唤醒线程
                    LockSupport.parkUntil(this, abstime);
                    //若是当前线程产生中断请求,就跳出循环, checkInterruptWhileWaiting方法能够看上面对此方法的介绍
                    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                       //退出循环 
                       break;
                }
                //节点已经在同步队列中,获取同步锁,只有获得锁才能继续执行,不然线程继续阻塞等待,acquireQueued方法返回当前线程是否被中断,此方法会在下面详细进行介绍 if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                   //将其标志节点interruptMode设置为从新中断标志位
                   interruptMode = REINTERRUPT;
                //若是当前节点的下一个节点不为空 
                if (node.nextWaiter != null)
                    //将已取消的节点从条件队列中移除能够看上面对unlinkCancelledWaiters方法介绍
                    unlinkCancelledWaiters();
                //是否要抛出中断异常,或者发出中断请求
                if (interruptMode != 0)
                    //能够看上面对reportInterruptAfterWait方法的介绍
                    reportInterruptAfterWait(interruptMode);
                //返回表示此方法是正常超时结束,仍是由中断退出结束 
                return !timedout;
            }
            
            //相比awaitNanos方法超时时间更加可控,能够传入不一样的超时单位
            //@return 节点对应的线程被中断是否比占有独占锁的线程调用signal、signalAll方法将当前节点从条件队列移到同步队列中以前,若是是返回值为false,不然返回true,表示正常超时,而不是由中断退出
            //新建个节点加入到同步队列中,并释放锁,让当前线程阻塞等待,直到被调用signal、signalAll方法,或者超时将当前节点从条件队列中移到同步队列中,在同步队列中阻塞获得获取锁。若是线程等待期间发出中断请求,则抛出中断异常
            public final boolean await(long time, TimeUnit unit) throws InterruptedException {
                //将超时时间转化为纳秒
                long nanosTimeout = unit.toNanos(time);
                //若是线程已被中断 
                if (Thread.interrupted())
                    //抛出中断异常
                    throw new InterruptedException();
                //为当前线程建立新的Node节点,而且将此节点加入到条件队列中,addConditionWaiter方法能够看上面对此方法的介绍
                Node node = addConditionWaiter();
                //释放当前线程占有的锁,并唤醒其余线程,fullRelease方法会在下面详细介绍到
                int savedState = fullyRelease(node);
                //获取死亡时间,即当前时间加上传入的超时时间 
                final long deadline = System.nanoTime() + nanosTimeout;
                //当前await方法是否正常超时结束,仍是由中断退出结束
                boolean timedout = false;
                //线程中断请求是在signal、signalAll方法将此节点加入到同步队列以前仍是以后的标志位
                int interruptMode = 0;
                //循环判断当前新建的节点是否在同步队列中,直到此节点在同步队列中退出循环,不然就阻塞当前线程,isOnSyncQueue方法会在下面进行介绍
                while (!isOnSyncQueue(node)) {
                    //若是传入的超时时间小于等于0
                    if (nanosTimeout <= 0L) { 
                        //transferAfterCanceledWait方法,看下面的详细介绍 
                        timedout = transferAfterCancelledWait(node);
                        //退出循环
                        break;
                    }
                    //若是超时时间大于等于spinForTimeoutThreshold阈值,才会阻塞当前线程,不然让其线程自旋一段时间
                    if (nanosTimeout >= spinForTimeoutThreshold)
                        //超时的阻塞当前线程,this是阻塞当前线程的监控对象
                        LockSupport.parkNanos(this, nanosTimeout);
                    //若是当前线程产生中断请求,就跳出循环, checkInterruptWhileWaiting方法能够看上面对此方法的介绍
                    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                        //退出循环
                        break;
                    //返回死亡时间减去当前时间的时间戳
                    nanosTimeout = deadline - System.nanoTime();
                }
                //节点已经在同步队列中,获取同步锁,只有获得锁才能继续执行,不然线程继续阻塞等待,acquireQueued方法返回当前线程是否被中断,此方法会在下面详细进行介绍
                if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                    //将其标志节点interruptMode设置为从新中断标志位
                    interruptMode = REINTERRUPT;
                //若是当前节点的下一个节点不为空 
                if (node.nextWaiter != null)
                    //将已取消的节点从条件队列中移除能够看上面对unlinkCancelledWaiters方法介绍
                    unlinkCancelledWaiters();
                //是否要抛出中断异常,或者发出中断请求
                if (interruptMode != 0)
                    //能够看上面对reportInterruptAfterWait方法的介绍
                    reportInterruptAfterWait(interruptMode);
                //返回表示此方法是正常超时结束,仍是由中断退出结束 
                return !timedout;
            }
    
            //判断Condition实例的外部类AQS和传入进来的AQS是否相等,判断Condition实例是否归属于传入进来的AQS 
            final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
                // AbstractQueuedSynchronizer.this在内部类实例中常用,获取外部类的实例
                return sync == AbstractQueuedSynchronizer.this;
            }
            
            //判断条件队列中是否有等待的节点
            protected final boolean hasWaiters() {
                /调用hasWaiters方法的线程,不是拥有排他锁的线程就会IllegalMonitorStateException异常,Condition的使用只支持在排他锁下使用
                if (!isHeldExclusively())
                    throw new IllegalMonitorStateException();
                //从条件队列的头节点开始,循环的获取条件队列中的节点
                for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                    //判断条件队列中的是否有节点的状态值为CONDITION
                    if (w.waitStatus == Node.CONDITION)
                        //若是是直接返回true
                        return true;
                }
                //不然直接返回false
                return false;
            }
            
            //获取条件队列中有多少个等待节点(状态值为CONDITION) 
            protected final int getWaitQueueLength() {
               //调用getWaitQueueLength方法的线程,不是拥有排他锁的线程就会IllegalMonitorStateException异常,Condition的使用只支持在排他锁下使用
               if (!isHeldExclusively())
                    throw new IllegalMonitorStateException();
                //等待节点数目
                int n = 0;
                //从条件队列的头节点开始,循环的获取条件队列中的节点
                for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                    //若是条件队列中等待节点的状态值为CONDITION
                    if (w.waitStatus == Node.CONDITION)
                        //等待节点加1
                        ++n;
                }
                //返回等待节点
                return n;
            }
            
            //获取条件队列中全部等待节点(状态值为CONDITION)的线程,返回线程集合 
            protected final Collection<Thread> getWaitingThreads() {
                //调用getWaitingThreads方法的线程,不是拥有排他锁的线程就会IllegalMonitorStateException异常,Condition的使用只支持在排他锁下使用
                if (!isHeldExclusively())
                    throw new IllegalMonitorStateException();
                //全部等待节点对应的线程集合
                ArrayList<Thread> list = new ArrayList<Thread>();
                //从条件队列的头节点开始,循环的获取条件队列中的节点
                for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                    //若是条件队列的等待节点的状态值为CONDITION
                    if (w.waitStatus == Node.CONDITION) {
                        //获取等待节点对应的线程
                        Thread t = w.thread;
                        //若是节点对应的线程不为空
                        if (t != null)
                            //将其线程加入到集合中 
                            list.add(t);
                    }
                }
                //返回全部等待节点对应的线程集合
                return list;
            }
    }复制代码

5、同步队列

  1. 同步队列头head设置

    //经过UnSafe的cas函数设置AQS的属性head值,仅仅在enq方法中,返回设置释放成功,使用cas保证多线程安全
    private final boolean compareAndSetHead(Node update) {
        //cas经过AQS实例和其属性head偏移量,若是头结点为空,将其空设置为update值
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }
    
    // 从新设置同步队列头结点head,只在acquire系列的方法中调用
    private void setHead(Node node) {
        head = node;
        //当前节点对应的当前线程已经获取到锁了,将当前节点对应的线程置为空
        node.thread = null;
        //当前节点前一个节点已经没有意义,将当前节点对应的前置节点置为空
        node.prev = null;
    }
    复制代码
  2. 同步队列尾tail设置

    //经过CAS函数设置tail值,仅仅在enq方法中调用,经过CAS函数设置tail值,保证多线程安全
    private final boolean compareAndSetTail(Node expect, Node update) {
            return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }
    
    // 向同步队列尾插入新节点,若是队列没有初始化,先初始化同步队列的头尾节点。返回原先的同步队列尾节点
     private Node enq(final Node node) {
            for (;;) {
                //获取同步队列的尾节点
                Node t = tail;
                //t尾节点为空,表示队列为空,先初始化队列
                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;
                    }
                }
            }
    }
    复制代码

6、独占锁

  1. 独占锁的获取

    //获取独占锁。若是没有立刻获取到,线程就会阻塞等待,直到获取到独占锁。不会响应中断异常
    public final void acquire(int arg) {
        //1. 当前线程先调用tryAcquire方法,尝试获取独占锁,若是返回true,表示获取到锁,不须要执行acquireQueued方法。
        //2. 若是tryAcquire方法获取独占锁失败,调用acquireQueued方法,先调用addWaiter方法为当前线程建立一个状态为独占模式的节点Node,并使用cas将其作为同步队列尾节点加入队列中,
        //若是当前加入节点的前置节点为头节点,当前线程调用tryAcquire方法去尝试获取锁,若是不成功,就会根据前置节点的状态来判断是否让当前线程阻塞,当前线程阻塞被唤醒。
        //acquireQueued方法返回值表示在线程等待过程当中,是否有另外一个线程调用该线程的interrupt方法,发起中断请求。
        //tryAcquire是个模板方法,能够看下面对此方法的介绍,acquireQueued方法能够看下面对此方法的介绍
        if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            //当前线程执行acquireQueued方法的过程当中有其余线程调用该线程的interrupt方法,发起中断请求,从新调用当前线程的interrupt方法,中断请求
            selfInterrupt();
    }
    
     // 尝试去获取独占锁,当即返回。若是返回true表示获取独占锁成功,此方法为模板方法,须要子类进行重写,能够看下面ReentrantReadWriteLock类中对AQS的tryAcquire方法实现
    protected boolean tryAcquire(int arg) {
         //抛出UnsupportedOperationException异常
         throw new UnsupportedOperationException();
    }
    
    //ReentrantReadWriteLock类中对AQS的tryAcquire方法实现,详细的介绍,会在分析ReentrantReadWriteLock源码时进行详细介绍
    //尝试获取同步队列的独占锁,与非公平锁最大的不一样就是调用hasQueuedPredecessors()方法,hasQueuedPredecessors方法返回true,表示等待线程队列中有一个线程在当前线程以前,根据公平锁的规则,当前线程不能获取锁。
    protected final boolean tryAcquire(int acquires) {
                //获取当前线程 
                Thread current = Thread.currentThread();
                //获取当前锁的状态,即AQS中的属性值
                int c = getState();
                //由状态获取独占锁的个数,锁的状态也是根据独占锁的个数或者共享锁的个数来进行判断
                int w = exclusiveCount(c);
                //若是c==0表示当前锁是空闲的,若是锁状态不等于0,代表锁状态有多是读锁或者写锁
                if (c != 0) {
                    //若是独占锁的个数等于0,代表当前锁属于共享锁模式,直接返回失败,若是独占锁的个数不等于0,而且当前拥有独占锁的线程不是当前,也是直接返回失败
                    if (w == 0 || current != getExclusiveOwnerThread())
                        return false;
                    //若是独占锁的个数加上传入进来的请求独占锁个数大于MAX_COUNT,直接抛出错误,超过最大的独占锁个数
                    if (w + exclusiveCount(acquires) > MAX_COUNT)
                        throw new Error("Maximum lock count exceeded");
                    //不然的话更新锁的状态 
                    setState(c + acquires);
                    //返回获取独占锁成功
                    return true;
                }
                //非公平锁writerShouldBlock直接返回false,公平锁writeShouldBlock会调用hasQueuedPredecessors方法
                if (writerShouldBlock() ||
                    !compareAndSetState(c, c + acquires))
                    //返回获取独占锁失败
                    return false;
                //将当前线程设置为拥有独占锁的线程
                setExclusiveOwnerThread(current);
                //返回获取独占锁成功
                return true;
    }
    
    /** * 获取独占锁的acquire系列方法,都会使用这个方法来获取独占锁 * 循环经过tryAcquire方法不断去获取锁,若是没有获取成功,若是此节点的前置节点的状态值为SIGNAL * 需调用parkAndCheckInterrupt方法,让当前线程阻塞 * @param node 想要获取独占锁锁的节点 * @param arg 获取独占锁的个数 * @return 返回true,表示在线程等待的过程当中,线程被中断了 */
    final boolean acquireQueued(final Node node, int arg) {
            //设置失败的标志位
            boolean failed = true;
            try {
                //表示节点对应的线程在等待过程当中,是否被中断的标志位
                boolean interrupted = false;
                //经过死循环,直到node节点对应的线程获取到锁,才返回
                for (;;) {
                    //获取当前节点的前置节点
                    final Node p = node.predecessor();
                    //若是当前节点的前一个节点为同步队列的头节点head,当前线程尝试使用tryAcquire方法获取锁,若是获取锁成功,那么当前线程就不须要阻塞等待,继续执行
                    if (p == head && tryAcquire(arg)) {
                        //将节点node设置为同步队列的头节点
                        setHead(node);
                        //将节点node的前置节点设置为空,加快gc
                        p.next = null; // help GC
                        //失败的标志位设置为false
                        failed = false;
                        //返回是否中断的标志位 
                        return interrupted;
                    }
                    //判断当前节点的前置节点的状态值是否为SIGNAL,若是是调用parkAndCheckInterrupt方法阻塞当前线程,shouldParkAfterFailedAcquire和parkAndCheckInterrupt方法会在下面详细进行介绍
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        //若是方法parkAndCheckInterrupt的返回值为true,代表节点对应的线程在等待时,有其余线程调用此线程的interrupt方法,中断请求
                        interrupted = true;
                }
            } finally {
                //在获取独占锁的过程当中失败,将当前节点从同步队列中移除
                if (failed)
                    //cancelAcquire方法会在下面详细进行介绍
                    cancelAcquire(node);
            }
    }
    
    /** * 根据前一个节点pred的状态,来判断当前节点对应的线程是否应该被阻塞 * @param pred : node节点的前一个节点 * @param node : 要获取独占锁的节点 * @return 返回true 表示当前线程应该被阻塞,而后调用parkAndCheckInterrupt方法来阻塞当前线程 */
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
            //获取前置节点的状态值
            int ws = pred.waitStatus;
            //若是前置节点的状态值为SIGNAL 
            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;
    }
    
    private final boolean parkAndCheckInterrupt() {
            //阻塞当前线程
            LockSupport.park(this);
            //当前线程被唤醒后,返回当前线程的中断标志位
            return Thread.interrupted();
    }
    
    //将传入进来的节点从同步队列中移除,将传入节点对应的线程置为空,状态置为CANCELLED
    private void cancelAcquire(Node node) {
            //若是当前节点为空,直接跳过
            if (node == null)
                return;
            //将当前节点对应的线程置为空
            node.thread = null;
    
            //获取当前要取消节点的前置节点
            Node pred = node.prev;
            //循环跳过前置节点状态为CANNELLED的值
            while (pred.waitStatus > 0)
                node.prev = pred = pred.prev;
    
            //获取状态不是取消的前置的节点的下一个节点,在设置前置节点的下一个节点使用到
            Node predNext = pred.next;
    
            //将当前要取消的节点状态赋值为CANCELLED
            node.waitStatus = Node.CANCELLED;
    
            //若是要取消节点为尾节点,将尾节点设置为要取消节点的前一个节点
            if (node == tail && compareAndSetTail(node, pred)) {
                //若是设置成功,将要取消节点的前置节点的下一个节点设置为空
                compareAndSetNext(pred, predNext, null);
            } else {
                int ws;
                //若是前置不是头节点,而且前置节点的状态值为SIGNAL,或者 
                if (pred != head &&
                    ((ws = pred.waitStatus) == Node.SIGNAL ||
                     (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                    pred.thread != null) {
                    //获取要取消节点的下一个节点
                    Node next = node.next;
                    //要取消节点的下一个节点不为空,而且状态值小于等于0,即不是取消状态值CANCELLED 
                    if (next != null && next.waitStatus <= 0)
                        //将要取消节点的前置节点和要取消节点的下一节点链接起来
                        compareAndSetNext(pred, predNext, next);
                } else {
                    //不然的话唤醒node节点的下一个节点,在下面会对unparkSuccessor方法进行详细介绍
                    unparkSuccessor(node);
                }
                //将要取消节点的下一节点设置为自身,加快gc
                node.next = node; // help GC
            }
    }
    
    //唤醒传入节点的下一个不为空、状态值不是已取消CANCELLED节点对应的线程
    private void unparkSuccessor(Node node) {
            //获取传入节点的状态
            int ws = node.waitStatus;
            //若是状态小于0,将其状态设置为0 
            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)
                    //t节点不是已取消节点
                    if (t.waitStatus <= 0)
                        //将下一节点s赋值为t
                        s = t;
            }
            //若是下一节点s不为空
            if (s != null)
                //唤醒此节点s对应的线程
                LockSupport.unpark(s.thread);
    }
    复制代码

  2. 独占锁的释放

    //调用release方法的线程,是拥有独占锁的线程,释放独占锁的操做
    public final boolean release(int arg) {
            //线程首先调用tryRelease方法,尝试去释放锁,此方法为模板方法,由子类具体实现
            if (tryRelease(arg)) {
                //若是tryRelease释放锁成功,获取同步队列的头结点
                Node h = head;
                //若是头结点不为空,而且状态值不等于0,无论头结点是已取消,仍是其余状态 
                if (h != null && h.waitStatus != 0)
                    //唤醒头结点的下一个不为空,而且状态值不为CANCELLED的下一个节点,能够看上面对unparkSuccessor方法的介绍
                    unparkSuccessor(h);
                //释放独占锁成 
                return true;
            }
            //释放独占锁失败
            return false;
    }
    
    //AQS的模板方法,由具体的子类实现
    protected boolean tryRelease(int arg) {
        //抛出UnsupportedOperationException异常
        throw new UnsupportedOperationException();
    }
    
    //ReentrantReadWriteLock中Sync的tryRelease方法实现
    protected final boolean tryRelease(int releases) {
                //判断当前尝试释放锁的线程,是不是拥有独占锁的线程,若是不是抛出IllegalMonitorStateException异常
                if (!isHeldExclusively())
                    throw new IllegalMonitorStateException();
                //将其锁的状态值减去要释放的独占锁的个数 
                int nextc = getState() - releases;
                //若是nextc为0,表示独占锁是否成功
                boolean free = exclusiveCount(nextc) == 0;
                if (free)
                    //若是锁释放成功,将其记录拥有独占锁的线程的记录置为空
                    setExclusiveOwnerThread(null);
                //设置锁的状态 
                setState(nextc);
                //返回独占锁释放是否成功 
                return free;
    }
    
    复制代码

7、共享锁

  1. 共享锁的获取

    //获取共享锁,不响应中断,不会抛出中断异常
    public final void acquireShared(int arg) {
            //当前线程调用tryAcquireShared尝试去获取共享锁,若是返回值小于0表示获取共享锁失败
            if (tryAcquireShared(arg) < 0)
                // 调用doAcquireShared方法去获取共享锁,tryAcquireShared、doAcquireShared方法会在下面详细进行介绍
                doAcquireShared(arg);
    
    }
    
    
    //尝试获取共享锁,AQS的模板方法,由具体的子类进行实现
    protected int tryAcquireShared(int arg) {
            //抛出UnsupportedOperationException异常
            throw new UnsupportedOperationException();
    }
    
    //ReentrantReadWriteLock类对tryAcquireShared方法的实现,会在ReentrantReadWriteLock源码的分析中进行详细的介绍
    protected final int tryAcquireShared(int unused) {
                //获取当前线程
                Thread current = Thread.currentThread();
                //获取锁的状态 
                int c = getState();
                //exclusiveCount根据锁的状态获取独占锁的个数若是不等于0,而且拥有此独占锁的线程不是当前线程,直接返回-1失败
                if (exclusiveCount(c) != 0 &&
                    getExclusiveOwnerThread() != current)
                    return -1;
                //根据锁的状态获取共享锁的个数 
                int r = sharedCount(c);
                //获取共享锁,当前线程是否须要阻塞,readerShouldBlock方法分为公平锁和非公平锁的不一样实现,公平锁会调用hasQueuedPredecessors方法,判断同步队列中前面是否有节点,有阻塞,非公平锁会
                //调用apparentlyFirstQueuedIsExclusive方法,判断头节点的状态是不是独占锁模式,若是是阻塞当前线程,不然继续执行。而且共享锁的个数得小于MAX_COUNT 
                if (!readerShouldBlock() &&
                    r < MAX_COUNT &&
                    //使用cas将当前锁的状态加上65535,即高16位存放共享锁的个数
                    compareAndSetState(c, c + SHARED_UNIT)) {
                    //若是原先共享锁的个数为0
                    if (r == 0) {
                        //将当前线程赋值给第一个获取共享锁的线程firstReader 
                        firstReader = current;
                        //当前线程持有的共享锁个数
                        firstReaderHoldCount = 1;
                    } else if (firstReader == current) {//锁的状态共享锁原先就有被获取,而且第一个持有的线程是当前线程,firstReaderHoldCount++操做,持有共享锁个数加1操做
                        //第一个获取共享锁的线程持有的共享锁个数加1操做
                        firstReaderHoldCount++;
                    } else {
                        //获取上一次缓存的线程的HoldCounter,HoldCounter实例是存放一个线程已获取的共享锁个数,及线程id
                        HoldCounter rh = cachedHoldCounter;
                        //上一次缓存的HoldCounter实例为空,或者HoldCounter实例里的线程id和当期线程id不相等
                        if (rh == null || rh.tid != getThreadId(current))
                            //从新获取当前线程对应的HoldCounter实例
                            cachedHoldCounter = rh = readHolds.get();
                        //若是当前线程对应的HoldCounter实例的线程获取共享锁的个数为0,从新将rh设置到ThreadLocal,ThreadLocal不清楚的能够看下个人另外一篇对此的源码分析
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        //不然线程对应的HoldCounter实例的线程已获取的共享锁个数进行加1操做 
                        rh.count++;
                    }
                    //返回1,表示获取共享锁成功
                    return 1;
                }
                //fullTryAcquireShared能够看下面对此方法的介绍 
                return fullTryAcquireShared(current);
    }
    
    //ReentrantReadWriteLock类的fullTryAcquireShared方法,详细的会再ReentrantReadWriteLock源码分析进行介绍
    final int fullTryAcquireShared(Thread current) {
                HoldCounter rh = null;
                //死循环的获取共享锁 
                for (;;) {
                    //获取锁的状态 
                    int c = getState();
                    //若是当前锁状态是独占锁,而且拥有独占锁的线程不是当前线程直接返回-1失败
                    if (exclusiveCount(c) != 0) {
                        if (getExclusiveOwnerThread() != current)
                            return -1;
                      //当前线程是否须要阻塞,readerShouldBlock方法分为公平锁和非公平锁的不一样实现,公平锁会调用hasQueuedPredecessors方法,判断同步队列中前面是否有节点,有阻塞,非公平锁会调用apparentlyFirstQueuedIsExclusive方法,判断头节点的状态是不是独占锁模式,若是是阻塞当前线程 
                    } else if (readerShouldBlock()) {
                        //若是当前线程就是第一个获取共享锁的线程,不作任何操做 
                        if (firstReader == current) {
                            // assert firstReaderHoldCount > 0;
                        } else {
                            if (rh == null) {
                                //获取上一次缓存的HoldCounter实例
                                rh = cachedHoldCounter;
                                //HoldCounter实例为空,而且HoldCounter实例不属于当前线程
                                if (rh == null || rh.tid != getThreadId(current)) {
                                    //获取当前线程对应的HoldCounter实例 
                                    rh = readHolds.get();
                                    //若是当前线程获取共享锁个数为0,将HoldCounter实例从ThreadLocal中移除 
                                    if (rh.count == 0)
                                        readHolds.remove();
                                }
                            }
                            //若是当前线程对应的HoldCounter实例的属性count等于0,即当前线程没有获取到共享锁,count当前线程获取的共享锁个数
                            if (rh.count == 0)
                                //返回-1失败
                                return -1;
                        }
                    }
                    //当前共享锁的个数大于MAX_COUNT,直接抛出一个错误
                    if (sharedCount(c) == MAX_COUNT)
                        throw new Error("Maximum lock count exceeded");
                    //共享锁是使用状态的高16位进行存储,为此加共享锁加65535
                    if (compareAndSetState(c, c + SHARED_UNIT)) {
                        //若是共享锁的个数为0,即没有获取过共享锁 
                        if (sharedCount(c) == 0) {
                            //将第一个获取共享锁的标识属性firstReader赋值为当前线程 
                            firstReader = current;
                            //获取共享锁的个数为1
                            firstReaderHoldCount = 1;
                           //锁的状态共享锁原先就有被获取,而且第一个持有的线程是当前线程,firstReaderHoldCount++操做,持有共享锁个数加1操做
                        } else if (firstReader == current) {
                            firstReaderHoldCount++;
                        } else {
                            //若是HoldCounter实例为空
                            if (rh == null)
                                //从缓存中获取上一次的HoldCounter实例
                                rh = cachedHoldCounter;
                            //HoldCounter实例为空,而且不属于当前线程 
                            if (rh == null || rh.tid != getThreadId(current))
                                //从ThreadLocal中从新获取HoldCounter实例 
                                rh = readHolds.get();
                            //若是当前线程对应的HoldCounter实例的线程获取共享锁的个数为0,从新将rh设置到ThreadLocal,ThreadLocal不清楚的能够看下个人另外一篇对此的源码分析
                            else if (rh.count == 0)
                                readHolds.set(rh);
                            //不然线程对应的HoldCounter实例的线程已获取的共享锁个数进行加1操做 
                            rh.count++;
                            //将缓存赋值为当前线程的HoldCounter
                            cachedHoldCounter = rh; // cache for release
                        }
                        //返回1表示获取共享锁成功
                        return 1;
                    }
                }
    }
    
    //死循环获取共享锁,根据当前节点的前一个节点状态来判断当前线程是否应该阻塞,直到获取到共享锁
    private void doAcquireShared(int arg) {
            //往同步队列中从尾节点加入一个模式为共享锁的节点,看上面对addWaiter方法的介绍
            final Node node = addWaiter(Node.SHARED);
            //获取共享锁是否成功
            boolean failed = true;
            try {
                //当前线程在获取共享锁的过程当中是否被中断的标志位
                boolean interrupted = false;
                for (;;) {
                    //获取当前节点的前一个节点 
                    final Node p = node.predecessor();
                    //若是当前节点的前置节点为表头
                    if (p == head) {
                        //使用上面介绍的tryAcquireShared尝试获取共享锁 
                        int r = tryAcquireShared(arg);
                        //
                        if (r >= 0) {
                            //能够看下面对setHeadAndPropagate方法的介绍
                            setHeadAndPropagate(node, r);
                            //将当前节点的前置节点下一个节点置为空
                            p.next = null; // help GC
                            //若是发生中断请求
                            if (interrupted)
                                selfInterrupt();
                            //获取共享锁成功
                            failed = false;
                            //直接返回 
                            return;
                        }
                    }
                    //判断当前节点的前置节点的状态值是否为SIGNAL,若是是调用parkAndCheckInterrupt方法阻塞当前线程,shouldParkAfterFailedAcquire和parkAndCheckInterrupt方法能够看上面对这两个方法的详细介绍
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        //parkAndCheckInterrupt返回值是否有中断请求
                        interrupted = true;
                }
            } finally {
                //若是失败
                if (failed)
                    //将当前节点从同步队列中移除,能够看上面对cancelAcquire方法的介绍
                    cancelAcquire(node);
            }
    }
    
    // 从新设置CLH队列头,若是CLH队列头的下一个节点为null或者共享模式,那么就要唤醒共享锁上等待的线程
    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) {
                // 获取新的CLH队列头的下一个节点s
                Node s = node.next;
                // 若是节点s是空或者共享模式节点,那么就要唤醒共享锁上等待的线程
                if (s == null || s.isShared())
                    //在下面共享锁的释放会对此方法进行介绍 
                    doReleaseShared();
            }
    }
    
    //若是当前线程在获取共享锁的过程当中,有其余线程调用当前线程的interrupt方法,中断请求,会抛出中断异常
    public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
            //若是当前线程被其余线程发起中断请求 
            if (Thread.interrupted())
                //抛出中断异常
                throw new InterruptedException();
            //tryAcquireShared能够看上面对此方法的介绍
            if (tryAcquireShared(arg) < 0)
                //能够看下面对doAcquireSharedInterruptibly的介绍
                doAcquireSharedInterruptibly(arg);
    }
    
    //超时的获取共享锁,而且响应中断请求,抛出中断异常
    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
            //若是当前线程被其余线程发起中断请求 
            if (Thread.interrupted())
                //抛出中断异常
                throw new InterruptedException();
            //tryAcquireShared能够看上面对此方法的介绍
            return tryAcquireShared(arg) >= 0 ||
                //能够看下面对doAcquireSharedNanos的介绍
                doAcquireSharedNanos(arg, nanosTimeout);
    }
    
    private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {
            //往同步队列中从尾节点加入一个模式为共享锁的节点,看上面对addWaiter方法的介绍
            final Node node = addWaiter(Node.SHARED);
            //执行是否失败的标志位,若是失败会将此节点从同步队列中移除
            boolean failed = true;
            try {
                //死循环的获取共享锁,除非获取共享锁成功,获取线程在阻塞的过程当中,被中断,抛出中断异常
                for (;;) {
                    //获取当前节点的前一个节点 
                    final Node p = node.predecessor();
                    //若是当前节点的前置节点为表头 
                    if (p == head) {
                        //使用上面介绍的tryAcquireShared尝试获取共享锁 
                        int r = tryAcquireShared(arg);
                        if (r >= 0) {
                            //能够看上面对setHeadAndPropagate方法的介绍
                            setHeadAndPropagate(node, r);
                            //将当前节点的前置节点下一个节点置为空
                            p.next = null; // help GC
                            //获取共享锁成功
                            failed = false;
                            //直接返回 
                            return;
                        }
                    }
                    //判断当前节点的前置节点的状态值是否为SIGNAL,若是是调用parkAndCheckInterrupt方法阻塞当前线程,shouldParkAfterFailedAcquire和parkAndCheckInterrupt方法能够看上面对这两个方法的详细介绍 
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        //若是线程在阻塞的过程当中,有其余线程调用当前线程的interrupt方法,中断请求,抛出中断异常
                        throw new InterruptedException();
                }
            } finally {
                //若是失败 
                if (failed)
                    //将当前节点从同步队列中移除,能够看上面对cancelAcquire方法的介绍 
                    cancelAcquire(node);
            }
    }
    
    //支持中断,会抛出中断异常,返回值是否获取共享锁成功
    private boolean doAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
            //若是传入进来的超时时间小于等于0直接返回失败
            if (nanosTimeout <= 0L)
                return false;
            //死亡时间,当前时间加上超市时间 
            final long deadline = System.nanoTime() + nanosTimeout;
            //往同步队列中从尾节点加入一个模式为共享锁的节点,看上面对addWaiter方法的介绍
            final Node node = addWaiter(Node.SHARED);
            //执行是否失败的标志位,若是失败会将此节点从同步队列中移除
            boolean failed = true;
            try {
                for (;;) {
                    //获取当前节点的前一个节点 
                    final Node p = node.predecessor();
                    //若是当前节点的前置节点为表头 
                    if (p == head) {
                        //使用上面介绍的tryAcquireShared尝试获取共享锁 
                        int r = tryAcquireShared(arg);
                        if (r >= 0) {
                            //能够看上面对setHeadAndPropagate方法的介绍
                            setHeadAndPropagate(node, r);
                           //将当前节点的前置节点下一个节点置为空
                            p.next = null; // help GC
                            //获取共享锁成功
                            failed = false;
                            //直接返回 
                            return;
                        }
                    }
                    //获取剩余的超时时间
                    nanosTimeout = deadline - System.nanoTime();
                    //若是在超时时间仍是没有获取到共享锁,直接返回失败 
                    if (nanosTimeout <= 0L)
                        return false;
                    //判断当前节点的前置节点的状态值是否为SIGNAL,若是是调用parkAndCheckInterrupt方法阻塞当前线程,shouldParkAfterFailedAcquire和parkAndCheckInterrupt方法能够看上面对这两个方法的详细介绍 
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        nanosTimeout > spinForTimeoutThreshold) //而且超时时间大于必定的阈值不然让其自旋一段时间
                        //使用LockSupport阻塞当前线程
                        LockSupport.parkNanos(this, nanosTimeout);
                    //若是当前线程在阻塞过程当中被中断
                    if (Thread.interrupted())
                        //直接抛出中断异常 
                        throw new InterruptedException();
                }
            } finally {
                //若是失败 
                if (failed)
                    //将当前节点从同步队列中移除,能够看上面对cancelAcquire方法的介绍 
                    cancelAcquire(node);
            }
    }
    复制代码

  2. 共享锁的释放

    //释放共享锁
    public final boolean releaseShared(int arg) {
        //尝试释放共享锁
        if (tryReleaseShared(arg)) {
            //唤醒等待共享锁的线程
            doReleaseShared();
            return true;
        }
        return false;
    }                        
    
    //尝试去释放共享锁,AQS的模板方法,由不一样的子类进行实现
    protected boolean tryReleaseShared(int arg) {
        throw new UnsupportedOperationException();
    }
    
    //ReentrantReadWriteLock类的tryReleaseShared方法实现
    protected final boolean tryReleaseShared(int unused) {
                //获取当前线程 
                Thread current = Thread.currentThread();
    			//若是当前线程是第一个获取共享锁的线程 
                if (firstReader == current) {
                    // assert firstReaderHoldCount > 0;
    				//第一个获取共享锁的线程持有的共享锁数等于1,将firstReader置为空 
                    if (firstReaderHoldCount == 1)
                        firstReader = null;
                    else
    				    //第一个获取共享锁的线程持有的共享锁数作减1操做
                        firstReaderHoldCount--;
                } else {
    			    //获取上一次缓存的HoldCounter实例
                    HoldCounter rh = cachedHoldCounter;
    				//HoldCounter实例rh为空,或者rh不属于当前线程
                    if (rh == null || rh.tid != getThreadId(current))
    				    //从新获取当前线程的HoldCounter实例
                        rh = readHolds.get();
    				//若是当前线程持有的共享锁个数 
                    int count = rh.count;
                    if (count <= 1) {
    				    //从ThreadLocal中移除当前线程的HoldCounter实例 
                        readHolds.remove();
    					//count <= 0表示当前线程就没有获取到读锁(共享锁),这里释放就抛出异常
                        if (count <= 0)
                            throw unmatchedUnlockException();
                    }
    				//当前线程的持有共享锁个数作减1操做
                    --rh.count;
                } 
    			//死循环的释放锁,若是当前锁的共享锁个数为0,返回true,代表共享锁释放成功
                for (;;) {
                    int c = getState();
                    int nextc = c - SHARED_UNIT;
                    if (compareAndSetState(c, nextc))
                        return nextc == 0;
                }
    }
    
    //唤醒等待共享锁的线程
    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;
                        // 唤醒节点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;
            }
    }复制代码
相关文章
相关标签/搜索